0024250: TKOpenGl - per-pixel lighting using GLSL program (Phong shading)
[occt.git] / src / OpenGl / OpenGl_ShaderProgram.cxx
1 // Created on: 2013-09-19
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #include <OSD_File.hxx>
21 #include <OSD_Protection.hxx>
22
23 #include <Standard_Assert.hxx>
24 #include <Standard_Atomic.hxx>
25 #include <TCollection_ExtendedString.hxx>
26
27 #include <OpenGl_Context.hxx>
28 #include <OpenGl_ShaderProgram.hxx>
29 #include <OpenGl_ShaderManager.hxx>
30
31 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource)
32 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource)
33
34 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
35
36 // Declare OCCT-specific OpenGL/GLSL shader variables
37 Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
38 {
39   /* OpenGl_OCC_MODEL_WORLD_MATRIX */ "occModelWorldMatrix",
40   /* OpenGl_OCC_WORLD_VIEW_MATRIX */ "occWorldViewMatrix",
41   /* OpenGl_OCC_PROJECTION_MATRIX */ "occProjectionMatrix",
42   /* OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE */ "occModelWorldMatrixInverse",
43   /* OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE */ "occWorldViewMatrixInverse",
44   /* OpenGl_OCC_PROJECTION_MATRIX_INVERSE */ "occProjectionMatrixInverse",
45   /* OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE */ "occModelWorldMatrixTranspose",
46   /* OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE */ "occWorldViewMatrixTranspose",
47   /* OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE */ "occProjectionMatrixTranspose",
48   /* OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE */ "occModelWorldMatrixInverseTranspose",
49   /* OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE */ "occWorldViewMatrixInverseTranspose",
50   /* OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE */ "occProjectionMatrixInverseTranspose",
51
52   /* OpenGl_OCC_CLIP_PLANE_0_EQUATION */ "occClipPlanes[0].Equation",
53   /* OpenGl_OCC_CLIP_PLANE_1_EQUATION */ "occClipPlanes[1].Equation",
54   /* OpenGl_OCC_CLIP_PLANE_2_EQUATION */ "occClipPlanes[2].Equation",
55   /* OpenGl_OCC_CLIP_PLANE_3_EQUATION */ "occClipPlanes[3].Equation",
56   /* OpenGl_OCC_CLIP_PLANE_4_EQUATION */ "occClipPlanes[4].Equation",
57   /* OpenGl_OCC_CLIP_PLANE_5_EQUATION */ "occClipPlanes[5].Equation",
58   /* OpenGl_OCC_CLIP_PLANE_6_EQUATION */ "occClipPlanes[6].Equation",
59   /* OpenGl_OCC_CLIP_PLANE_7_EQUATION */ "occClipPlanes[7].Equation",
60
61   /* OpenGl_OCC_CLIP_PLANE_0_SPACE */ "occClipPlanes[0].Space",
62   /* OpenGl_OCC_CLIP_PLANE_1_SPACE */ "occClipPlanes[1].Space",
63   /* OpenGl_OCC_CLIP_PLANE_2_SPACE */ "occClipPlanes[2].Space",
64   /* OpenGl_OCC_CLIP_PLANE_3_SPACE */ "occClipPlanes[3].Space",
65   /* OpenGl_OCC_CLIP_PLANE_4_SPACE */ "occClipPlanes[4].Space",
66   /* OpenGl_OCC_CLIP_PLANE_5_SPACE */ "occClipPlanes[5].Space",
67   /* OpenGl_OCC_CLIP_PLANE_6_SPACE */ "occClipPlanes[6].Space",
68   /* OpenGl_OCC_CLIP_PLANE_7_SPACE */ "occClipPlanes[7].Space",
69
70   /* OpenGl_OCC_LIGHT_SOURCE_COUNT */ "occLightSourcesCount",
71
72   /* OpenGl_OCC_LIGHT_SOURCE_0_TYPE */ "occLightSources[0].Type",
73   /* OpenGl_OCC_LIGHT_SOURCE_1_TYPE */ "occLightSources[1].Type",
74   /* OpenGl_OCC_LIGHT_SOURCE_2_TYPE */ "occLightSources[2].Type",
75   /* OpenGl_OCC_LIGHT_SOURCE_3_TYPE */ "occLightSources[3].Type",
76   /* OpenGl_OCC_LIGHT_SOURCE_4_TYPE */ "occLightSources[4].Type",
77   /* OpenGl_OCC_LIGHT_SOURCE_5_TYPE */ "occLightSources[5].Type",
78   /* OpenGl_OCC_LIGHT_SOURCE_6_TYPE */ "occLightSources[6].Type",
79   /* OpenGl_OCC_LIGHT_SOURCE_7_TYPE */ "occLightSources[7].Type",
80
81   /* OpenGl_OCC_LIGHT_SOURCE_0_HEAD */ "occLightSources[0].Head",
82   /* OpenGl_OCC_LIGHT_SOURCE_1_HEAD */ "occLightSources[1].Head",
83   /* OpenGl_OCC_LIGHT_SOURCE_2_HEAD */ "occLightSources[2].Head",
84   /* OpenGl_OCC_LIGHT_SOURCE_3_HEAD */ "occLightSources[3].Head",
85   /* OpenGl_OCC_LIGHT_SOURCE_4_HEAD */ "occLightSources[4].Head",
86   /* OpenGl_OCC_LIGHT_SOURCE_5_HEAD */ "occLightSources[5].Head",
87   /* OpenGl_OCC_LIGHT_SOURCE_6_HEAD */ "occLightSources[6].Head",
88   /* OpenGl_OCC_LIGHT_SOURCE_7_HEAD */ "occLightSources[7].Head",
89
90   /* OpenGl_OCC_LIGHT_SOURCE_0_AMBIENT */ "occLightSources[0].Ambient",
91   /* OpenGl_OCC_LIGHT_SOURCE_1_AMBIENT */ "occLightSources[1].Ambient",
92   /* OpenGl_OCC_LIGHT_SOURCE_2_AMBIENT */ "occLightSources[2].Ambient",
93   /* OpenGl_OCC_LIGHT_SOURCE_3_AMBIENT */ "occLightSources[3].Ambient",
94   /* OpenGl_OCC_LIGHT_SOURCE_4_AMBIENT */ "occLightSources[4].Ambient",
95   /* OpenGl_OCC_LIGHT_SOURCE_5_AMBIENT */ "occLightSources[5].Ambient",
96   /* OpenGl_OCC_LIGHT_SOURCE_6_AMBIENT */ "occLightSources[6].Ambient",
97   /* OpenGl_OCC_LIGHT_SOURCE_7_AMBIENT */ "occLightSources[7].Ambient",
98
99   /* OpenGl_OCC_LIGHT_SOURCE_0_DIFFUSE */ "occLightSources[0].Diffuse",
100   /* OpenGl_OCC_LIGHT_SOURCE_1_DIFFUSE */ "occLightSources[1].Diffuse",
101   /* OpenGl_OCC_LIGHT_SOURCE_2_DIFFUSE */ "occLightSources[2].Diffuse",
102   /* OpenGl_OCC_LIGHT_SOURCE_3_DIFFUSE */ "occLightSources[3].Diffuse",
103   /* OpenGl_OCC_LIGHT_SOURCE_4_DIFFUSE */ "occLightSources[4].Diffuse",
104   /* OpenGl_OCC_LIGHT_SOURCE_5_DIFFUSE */ "occLightSources[5].Diffuse",
105   /* OpenGl_OCC_LIGHT_SOURCE_6_DIFFUSE */ "occLightSources[6].Diffuse",
106   /* OpenGl_OCC_LIGHT_SOURCE_7_DIFFUSE */ "occLightSources[7].Diffuse",
107
108   /* OpenGl_OCC_LIGHT_SOURCE_0_SPECULAR */ "occLightSources[0].Specular",
109   /* OpenGl_OCC_LIGHT_SOURCE_1_SPECULAR */ "occLightSources[1].Specular",
110   /* OpenGl_OCC_LIGHT_SOURCE_2_SPECULAR */ "occLightSources[2].Specular",
111   /* OpenGl_OCC_LIGHT_SOURCE_3_SPECULAR */ "occLightSources[3].Specular",
112   /* OpenGl_OCC_LIGHT_SOURCE_4_SPECULAR */ "occLightSources[4].Specular",
113   /* OpenGl_OCC_LIGHT_SOURCE_5_SPECULAR */ "occLightSources[5].Specular",
114   /* OpenGl_OCC_LIGHT_SOURCE_6_SPECULAR */ "occLightSources[6].Specular",
115   /* OpenGl_OCC_LIGHT_SOURCE_7_SPECULAR */ "occLightSources[7].Specular",
116
117   /* OpenGl_OCC_LIGHT_SOURCE_0_POSITION */ "occLightSources[0].Position",
118   /* OpenGl_OCC_LIGHT_SOURCE_1_POSITION */ "occLightSources[1].Position",
119   /* OpenGl_OCC_LIGHT_SOURCE_2_POSITION */ "occLightSources[2].Position",
120   /* OpenGl_OCC_LIGHT_SOURCE_3_POSITION */ "occLightSources[3].Position",
121   /* OpenGl_OCC_LIGHT_SOURCE_4_POSITION */ "occLightSources[4].Position",
122   /* OpenGl_OCC_LIGHT_SOURCE_5_POSITION */ "occLightSources[5].Position",
123   /* OpenGl_OCC_LIGHT_SOURCE_6_POSITION */ "occLightSources[6].Position",
124   /* OpenGl_OCC_LIGHT_SOURCE_7_POSITION */ "occLightSources[7].Position",
125
126   /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_CUTOFF */ "occLightSources[0].SpotCutoff",
127   /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_CUTOFF */ "occLightSources[1].SpotCutoff",
128   /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_CUTOFF */ "occLightSources[2].SpotCutoff",
129   /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_CUTOFF */ "occLightSources[3].SpotCutoff",
130   /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_CUTOFF */ "occLightSources[4].SpotCutoff",
131   /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_CUTOFF */ "occLightSources[5].SpotCutoff",
132   /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_CUTOFF */ "occLightSources[6].SpotCutoff",
133   /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_CUTOFF */ "occLightSources[7].SpotCutoff",
134
135   /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_EXPONENT */ "occLightSources[0].SpotExponent",
136   /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_EXPONENT */ "occLightSources[1].SpotExponent",
137   /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_EXPONENT */ "occLightSources[2].SpotExponent",
138   /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_EXPONENT */ "occLightSources[3].SpotExponent",
139   /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_EXPONENT */ "occLightSources[4].SpotExponent",
140   /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_EXPONENT */ "occLightSources[5].SpotExponent",
141   /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_EXPONENT */ "occLightSources[6].SpotExponent",
142   /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_EXPONENT */ "occLightSources[7].SpotExponent",
143
144   /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_DIRECTION */ "occLightSources[0].SpotDirection",
145   /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_DIRECTION */ "occLightSources[1].SpotDirection",
146   /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_DIRECTION */ "occLightSources[2].SpotDirection",
147   /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_DIRECTION */ "occLightSources[3].SpotDirection",
148   /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_DIRECTION */ "occLightSources[4].SpotDirection",
149   /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_DIRECTION */ "occLightSources[5].SpotDirection",
150   /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_DIRECTION */ "occLightSources[6].SpotDirection",
151   /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_DIRECTION */ "occLightSources[7].SpotDirection",
152
153   /* OpenGl_OCC_LIGHT_SOURCE_0_CONST_ATTENUATION */ "occLightSources[0].ConstAttenuation",
154   /* OpenGl_OCC_LIGHT_SOURCE_1_CONST_ATTENUATION */ "occLightSources[1].ConstAttenuation",
155   /* OpenGl_OCC_LIGHT_SOURCE_2_CONST_ATTENUATION */ "occLightSources[2].ConstAttenuation",
156   /* OpenGl_OCC_LIGHT_SOURCE_3_CONST_ATTENUATION */ "occLightSources[3].ConstAttenuation",
157   /* OpenGl_OCC_LIGHT_SOURCE_4_CONST_ATTENUATION */ "occLightSources[4].ConstAttenuation",
158   /* OpenGl_OCC_LIGHT_SOURCE_5_CONST_ATTENUATION */ "occLightSources[5].ConstAttenuation",
159   /* OpenGl_OCC_LIGHT_SOURCE_6_CONST_ATTENUATION */ "occLightSources[6].ConstAttenuation",
160   /* OpenGl_OCC_LIGHT_SOURCE_7_CONST_ATTENUATION */ "occLightSources[7].ConstAttenuation",
161
162   /* OpenGl_OCC_LIGHT_SOURCE_0_LINEAR_ATTENUATION */ "occLightSources[0].LinearAttenuation",
163   /* OpenGl_OCC_LIGHT_SOURCE_1_LINEAR_ATTENUATION */ "occLightSources[1].LinearAttenuation",
164   /* OpenGl_OCC_LIGHT_SOURCE_2_LINEAR_ATTENUATION */ "occLightSources[2].LinearAttenuation",
165   /* OpenGl_OCC_LIGHT_SOURCE_3_LINEAR_ATTENUATION */ "occLightSources[3].LinearAttenuation",
166   /* OpenGl_OCC_LIGHT_SOURCE_4_LINEAR_ATTENUATION */ "occLightSources[4].LinearAttenuation",
167   /* OpenGl_OCC_LIGHT_SOURCE_5_LINEAR_ATTENUATION */ "occLightSources[5].LinearAttenuation",
168   /* OpenGl_OCC_LIGHT_SOURCE_6_LINEAR_ATTENUATION */ "occLightSources[6].LinearAttenuation",
169   /* OpenGl_OCC_LIGHT_SOURCE_7_LINEAR_ATTENUATION */ "occLightSources[7].LinearAttenuation",
170
171   /* OpenGl_OCCT_ACTIVE_SAMPLER */ "occActiveSampler",
172   /* OpenGl_OCCT_TEXTURE_ENABLE */ "occTextureEnable",
173   /* OpenGl_OCCT_DISTINGUISH_MODE */ "occDistinguishingMode",
174   /* OpenGl_OCCT_FRONT_MATERIAL_AMBIENT */ "occFrontMaterial.Ambient",
175   /* OpenGl_OCCT_BACK_MATERIAL_AMBIENT */ "occBackMaterial.Ambient",
176   /* OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE */ "occFrontMaterial.Diffuse",
177   /* OpenGl_OCCT_BACK_MATERIAL_DIFFUSE */ "occBackMaterial.Diffuse",
178   /* OpenGl_OCCT_FRONT_MATERIAL_SPECULAR */ "occFrontMaterial.Specular",
179   /* OpenGl_OCCT_BACK_MATERIAL_SPECULAR */ "occBackMaterial.Specular",
180   /* OpenGl_OCCT_FRONT_MATERIAL_EMISSION */ "occFrontMaterial.Emission",
181   /* OpenGl_OCCT_BACK_MATERIAL_EMISSION */ "occBackMaterial.Emission",
182   /* OpenGl_OCCT_FRONT_MATERIAL_SHININESS */ "occFrontMaterial.Shininess",
183   /* OpenGl_OCCT_BACK_MATERIAL_SHININESS */ "occBackMaterial.Shininess",
184   /* OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY */ "occFrontMaterial.Transparency",
185   /* OpenGl_OCCT_BACK_MATERIAL_TRANSPARENCY */ "occBackMaterial.Transparency"
186
187 };
188
189 // =======================================================================
190 // function : OpenGl_VariableSetterSelector
191 // purpose  : Creates new variable setter selector
192 // =======================================================================
193 OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
194 {
195   // Note: Add new variable setters here
196   mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
197     (Graphic3d_UniformValueTypeID<int>::ID,          new OpenGl_VariableSetter<int>())
198     (Graphic3d_UniformValueTypeID<float>::ID,        new OpenGl_VariableSetter<float>())
199     (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID,  new OpenGl_VariableSetter<OpenGl_Vec2>())
200     (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID,  new OpenGl_VariableSetter<OpenGl_Vec3>())
201     (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID,  new OpenGl_VariableSetter<OpenGl_Vec4>())
202     (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
203     (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
204     (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
205 }
206
207 // =======================================================================
208 // function : ~OpenGl_VariableSetterSelector
209 // purpose  : Releases memory resources of variable setter selector
210 // =======================================================================
211 OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
212 {
213   for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
214   {
215     delete anIt.Value();
216   }
217
218   mySetterList.Clear();
219 }
220
221 // =======================================================================
222 // function : Set
223 // purpose  : Sets generic variable to specified shader program
224 // =======================================================================
225 void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)&           theCtx,
226                                          const Handle(Graphic3d_ShaderVariable)& theVariable,
227                                          OpenGl_ShaderProgram*                   theProgram) const
228 {
229   Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
230     "The type of user-defined uniform variable is not supported...", );
231
232   mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
233 }
234
235 // =======================================================================
236 // function : OpenGl_ShaderProgram
237 // purpose  : Creates uninitialized shader program
238 // =======================================================================
239 OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
240 : myProgramID (NO_PROGRAM),
241   myProxy     (theProxy),
242   myShareCount(1)
243 {
244   memset (myCurrentState, 0, sizeof (myCurrentState));
245   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
246   {
247     myStateLocations[aVar] = INVALID_LOCATION;
248   }
249 }
250
251 // =======================================================================
252 // function : Initialize
253 // purpose  : Initializes program object with the list of shader objects
254 // =======================================================================
255 Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&     theCtx,
256                                                    const Graphic3d_ShaderObjectList& theShaders)
257 {
258   if (theCtx.IsNull() || !Create (theCtx))
259   {
260     return Standard_False;
261   }
262
263   OSD_File aDeclFile (Graphic3d_ShaderProgram::ShadersFolder() + "/Declarations.glsl");
264   if (!aDeclFile.Exists())
265   {
266     const TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
267     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
268                          GL_DEBUG_TYPE_ERROR_ARB,
269                          0,
270                          GL_DEBUG_SEVERITY_HIGH_ARB,
271                          aMsg);
272     return Standard_False;
273   }
274
275   TCollection_AsciiString aDeclarations;
276
277   aDeclFile.Open (OSD_ReadOnly, OSD_Protection());
278   aDeclFile.Read (aDeclarations, (int)aDeclFile.Size());
279   aDeclFile.Close();
280
281   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders);
282        anIter.More(); anIter.Next())
283   {
284     if (!anIter.Value()->IsDone())
285     {
286       const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
287       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
288                            GL_DEBUG_TYPE_ERROR_ARB,
289                            0,
290                            GL_DEBUG_SEVERITY_HIGH_ARB,
291                            aMsg);
292       return Standard_False;
293     }
294
295     Handle(OpenGl_ShaderObject) aShader;
296
297     // Note: Add support of other shader types here
298     switch (anIter.Value()->Type())
299     {
300       case Graphic3d_TOS_VERTEX:
301         aShader = new OpenGl_ShaderObject (GL_VERTEX_SHADER);
302         break;
303       case Graphic3d_TOS_FRAGMENT:
304         aShader = new OpenGl_ShaderObject (GL_FRAGMENT_SHADER);
305         break;
306     }
307
308     // Is unsupported shader type?
309     if (aShader.IsNull())
310     {
311       TCollection_ExtendedString aMsg = "Error! Unsupported shader type";
312       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
313                            GL_DEBUG_TYPE_ERROR_ARB,
314                            0,
315                            GL_DEBUG_SEVERITY_HIGH_ARB,
316                            aMsg);
317       return Standard_False;
318     }
319
320     if (!aShader->Create (theCtx))
321     {
322       aShader->Release (theCtx.operator->());
323       return Standard_False;
324     }
325
326     TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
327     if (anIter.Value()->Type() == Graphic3d_TOS_VERTEX)
328     {
329       aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
330     }
331
332     if (!aShader->LoadSource (theCtx, aSource))
333     {
334       const TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
335       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
336                            GL_DEBUG_TYPE_ERROR_ARB,
337                            0,
338                            GL_DEBUG_SEVERITY_HIGH_ARB,
339                            aMsg);
340       aShader->Release (theCtx.operator->());
341       return Standard_False;
342     }
343
344     if (!aShader->Compile (theCtx))
345     {
346       TCollection_AsciiString aLog;
347       aShader->FetchInfoLog (theCtx, aLog);
348       if (aLog.IsEmpty())
349       {
350         aLog = "Compilation log is empty.";
351       }
352       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
353                            GL_DEBUG_TYPE_ERROR_ARB,
354                            0,
355                            GL_DEBUG_SEVERITY_HIGH_ARB,
356                            TCollection_ExtendedString ("Failed to compile shader object. Compilation log:\n") + aLog);
357       aShader->Release (theCtx.operator->());
358       return Standard_False;
359     }
360     else if (theCtx->caps->glslWarnings)
361     {
362       TCollection_AsciiString aLog;
363       aShader->FetchInfoLog (theCtx, aLog);
364       if (!aLog.IsEmpty()
365        && !aLog.IsEqual ("No errors.\n"))
366       {
367         theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
368                              GL_DEBUG_TYPE_PORTABILITY_ARB,
369                              0,
370                              GL_DEBUG_SEVERITY_LOW_ARB,
371                              TCollection_ExtendedString ("Shader compilation log:\n") + aLog);
372       }
373     }
374
375     if (!AttachShader (theCtx, aShader))
376     {
377       aShader->Release (theCtx.operator->());
378       return Standard_False;
379     }
380   }
381
382   if (!Link (theCtx))
383   {
384     TCollection_AsciiString aLog;
385     FetchInfoLog (theCtx, aLog);
386     if (aLog.IsEmpty())
387     {
388       aLog = "Linker log is empty.";
389     }
390     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
391                          GL_DEBUG_TYPE_ERROR_ARB,
392                          0,
393                          GL_DEBUG_SEVERITY_HIGH_ARB,
394                          TCollection_ExtendedString ("Failed to link program object! Linker log:\n"));
395     return Standard_False;
396   }
397   else if (theCtx->caps->glslWarnings)
398   {
399     TCollection_AsciiString aLog;
400     FetchInfoLog (theCtx, aLog);
401     if (!aLog.IsEmpty()
402      && !aLog.IsEqual ("No errors.\n"))
403     {
404       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
405                            GL_DEBUG_TYPE_PORTABILITY_ARB,
406                            0,
407                            GL_DEBUG_SEVERITY_LOW_ARB,
408                            TCollection_ExtendedString ("GLSL linker log:\n") + aLog);
409     }
410   }
411
412   return Standard_True;
413 }
414
415 // =======================================================================
416 // function : ~OpenGl_ShaderProgram
417 // purpose  : Releases resources of shader program
418 // =======================================================================
419 OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
420 {
421   Release (NULL);
422 }
423
424 // =======================================================================
425 // function : AttachShader
426 // purpose  : Attaches shader object to the program object
427 // =======================================================================
428 Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)&      theCtx,
429                                                      const Handle(OpenGl_ShaderObject)& theShader)
430 {
431   if (myProgramID == NO_PROGRAM || theShader.IsNull())
432   {
433     return Standard_False;
434   }
435
436   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
437   {
438     if (theShader == anIter.Value())
439     {
440       return Standard_False;
441     }
442   }
443
444   myShaderObjects.Append (theShader);
445   theCtx->core20->glAttachShader (myProgramID, theShader->myShaderID);
446   return Standard_True;
447 }
448
449 // =======================================================================
450 // function : DetachShader
451 // purpose  : Detaches shader object to the program object
452 // =======================================================================
453 Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)&      theCtx,
454                                                      const Handle(OpenGl_ShaderObject)& theShader)
455 {
456   if (myProgramID == NO_PROGRAM
457    || theShader.IsNull())
458   {
459     return Standard_False;
460   }
461
462   OpenGl_ShaderList::Iterator anIter (myShaderObjects);
463   while (anIter.More())
464   {
465     if (theShader == anIter.Value())
466     {
467       myShaderObjects.Remove (anIter);
468       break;
469     }
470
471     anIter.Next();
472   }
473
474   if (!anIter.More())
475   {
476     return Standard_False;
477   }
478
479   theCtx->core20->glDetachShader (myProgramID, theShader->myShaderID);
480   return Standard_True;
481 }
482
483 // =======================================================================
484 // function : Link
485 // purpose  : Links the program object
486 // =======================================================================
487 Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx)
488 {
489   if (myProgramID == NO_PROGRAM)
490   {
491     return Standard_False;
492   }
493
494   theCtx->core20->glLinkProgram (myProgramID);
495
496   GLint aStatus = GL_FALSE;
497   theCtx->core20->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
498
499   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
500   {
501     myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
502   }
503
504   return aStatus != GL_FALSE;
505 }
506
507 // =======================================================================
508 // function : FetchInfoLog
509 // purpose  : Fetches information log of the last link operation
510 // =======================================================================
511 Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
512                                                      TCollection_AsciiString&      theOutput)
513 {
514   if (myProgramID == NO_PROGRAM)
515   {
516     return Standard_False;
517   }
518
519   GLint aLength = 0;
520   theCtx->core20->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
521   if (aLength > 0)
522   {
523     GLchar* aLog = (GLchar*) alloca (aLength);
524     memset (aLog, 0, aLength);
525     theCtx->core20->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
526     theOutput = aLog;
527   }
528   return Standard_True;
529 }
530
531 // =======================================================================
532 // function : Bind
533 // purpose  : Sets the program object as part of current rendering state
534 // =======================================================================
535 void OpenGl_ShaderProgram::Bind (const Handle(OpenGl_Context)& theCtx) const
536 {
537   if (myProgramID == NO_PROGRAM)
538   {
539     return;
540   }
541
542   theCtx->core20->glUseProgram (myProgramID);
543   theCtx->ShaderManager()->myIsPP = Standard_True;
544 }
545
546 // =======================================================================
547 // function : ApplyVariables
548 // purpose  : Fetches uniform variables from proxy shader program
549 // =======================================================================
550 Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
551 {
552   if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
553   {
554     return Standard_False;
555   }
556
557   for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
558   {
559     mySetterSelector.Set (theCtx, anIter.Value(), this);
560   }
561
562   myProxy->ClearVariables();
563   return Standard_True;
564 }
565
566 // =======================================================================
567 // function : BindWithVariables
568 // purpose  : Binds the program object and applies variables
569 // =======================================================================
570 Standard_Boolean OpenGl_ShaderProgram::BindWithVariables (const Handle(OpenGl_Context)& theCtx)
571 {
572   Bind (theCtx);
573   return ApplyVariables (theCtx);
574 }
575
576 // =======================================================================
577 // function : Unbind
578 // purpose  : Reverts to fixed-function graphics pipeline (FFP)
579 // =======================================================================
580 void OpenGl_ShaderProgram::Unbind (const Handle(OpenGl_Context)& theCtx)
581 {
582   if (theCtx->ShaderManager()->myIsPP)
583   {
584     theCtx->core20->glUseProgram (NO_PROGRAM);
585     theCtx->ShaderManager()->myIsPP = Standard_False;
586   }
587 }
588
589 // =======================================================================
590 // function : ActiveState
591 // purpose  : Returns index of last modification for specified state type
592 // =======================================================================
593 Standard_Size OpenGl_ShaderProgram::ActiveState (const OpenGl_UniformStateType theType) const
594 {
595   if (theType < MaxStateTypes)
596   {
597     return myCurrentState[theType];
598   }
599   return 0;
600 }
601
602 // =======================================================================
603 // function : UpdateState
604 // purpose  : Updates index of last modification for specified state type
605 // =======================================================================
606 void OpenGl_ShaderProgram::UpdateState (const OpenGl_UniformStateType theType,
607                                         const Standard_Size           theIndex)
608 {
609   if (theType < MaxStateTypes)
610   {
611     myCurrentState[theType] = theIndex;
612   }
613 }
614
615 // =======================================================================
616 // function : GetUniformLocation
617 // purpose  : Returns location (index) of the specific uniform variable
618 // =======================================================================
619 GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
620                                                 const GLchar*                 theName) const
621 {
622   return myProgramID != NO_PROGRAM
623        ? theCtx->core20->glGetUniformLocation (myProgramID, theName)
624        : INVALID_LOCATION;
625 }
626
627 // =======================================================================
628 // function : GetAttributeLocation
629 // purpose  : Returns location (index) of the generic vertex attribute
630 // =======================================================================
631 GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
632                                                   const GLchar*                 theName) const
633 {
634   return myProgramID != NO_PROGRAM
635        ? theCtx->core20->glGetAttribLocation (myProgramID, theName)
636        : INVALID_LOCATION;
637 }
638
639 // =======================================================================
640 // function : GetStateLocation
641 // purpose  : Returns location of the OCCT state uniform variable
642 // =======================================================================
643 GLint OpenGl_ShaderProgram::GetStateLocation (const GLuint theVariable) const
644 {
645   if (theVariable < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES)
646   {
647     return myStateLocations[theVariable];
648   }
649   return INVALID_LOCATION;
650 }
651
652 // =======================================================================
653 // function : GetUniform
654 // purpose  : Returns the value of the integer uniform variable
655 // =======================================================================
656 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
657                                                    const GLchar*                 theName,
658                                                    OpenGl_Vec4i&                 theValue) const
659 {
660   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
661 }
662
663 // =======================================================================
664 // function : GetUniform
665 // purpose  : Returns the value of the integer uniform variable
666 // =======================================================================
667 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
668                                                    GLint                         theLocation,
669                                                    OpenGl_Vec4i&                 theValue) const
670 {
671   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
672   {
673     return Standard_False;
674   }
675
676   theCtx->core20->glGetUniformiv (myProgramID, theLocation, theValue);
677   return Standard_True;
678 }
679
680 // =======================================================================
681 // function : GetUniform
682 // purpose  : Returns the value of the floating-point uniform variable
683 // =======================================================================
684 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
685                                                    const GLchar*                 theName,
686                                                    OpenGl_Vec4&                  theValue) const
687 {
688   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
689 }
690
691 // =======================================================================
692 // function : GetUniform
693 // purpose  : Returns the value of the floating-point uniform variable
694 // =======================================================================
695 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
696                                                    GLint                         theLocation,
697                                                    OpenGl_Vec4&                  theValue) const
698 {
699   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
700   {
701     return Standard_False;
702   }
703
704   theCtx->core20->glGetUniformfv (myProgramID, theLocation, theValue);
705   return Standard_True;
706 }
707
708 // =======================================================================
709 // function : GetAttribute
710 // purpose  : Returns the integer vertex attribute
711 // =======================================================================
712 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
713                                                      const GLchar*                 theName,
714                                                      OpenGl_Vec4i&                 theValue) const
715 {
716   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
717 }
718
719 // =======================================================================
720 // function : GetAttribute
721 // purpose  : Returns the integer vertex attribute
722 // =======================================================================
723 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
724                                                      GLint                         theIndex,
725                                                      OpenGl_Vec4i&                 theValue) const
726 {
727   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
728   {
729     return Standard_False;
730   }
731
732   theCtx->core20->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
733   return Standard_True;
734 }
735
736 // =======================================================================
737 // function : GetAttribute
738 // purpose  : Returns the floating-point vertex attribute
739 // =======================================================================
740 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
741                                                      const GLchar*                 theName,
742                                                      OpenGl_Vec4&                  theValue) const
743 {
744   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
745 }
746
747 // =======================================================================
748 // function : GetAttribute
749 // purpose  : Returns the floating-point vertex attribute
750 // =======================================================================
751 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
752                                                      GLint                         theIndex,
753                                                      OpenGl_Vec4&                  theValue) const
754 {
755   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
756   {
757     return Standard_False;
758   }
759
760   theCtx->core20->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
761   return Standard_True;
762 }
763
764 // =======================================================================
765 // function : SetUniform
766 // purpose  : Specifies the value of the integer uniform variable
767 // =======================================================================
768 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
769                                                    const GLchar*                 theName,
770                                                    GLint                         theValue)
771 {
772   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
773 }
774
775 // =======================================================================
776 // function : SetUniform
777 // purpose  : Specifies the value of the integer uniform variable
778 // =======================================================================
779 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
780                                                    GLint                         theLocation,
781                                                    GLint                         theValue)
782 {
783   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
784   {
785     return Standard_False;
786   }
787
788   theCtx->core20->glUniform1i (theLocation, theValue);
789   return Standard_True;
790 }
791
792 // =======================================================================
793 // function : SetUniform
794 // purpose  : Specifies the value of the floating-point uniform variable
795 // =======================================================================
796 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
797                                                    const GLchar*                 theName,
798                                                    GLfloat                       theValue)
799 {
800   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
801 }
802
803 // =======================================================================
804 // function : SetUniform
805 // purpose  : Specifies the value of the floating-point uniform variable
806 // =======================================================================
807 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
808                                                    GLint                         theLocation,
809                                                    GLfloat                       theValue)
810 {
811   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
812   {
813     return Standard_False;
814   }
815
816   theCtx->core20->glUniform1f (theLocation, theValue);
817   return Standard_True;
818 }
819
820 // =======================================================================
821 // function : SetUniform
822 // purpose  : Specifies the value of the integer uniform 2D vector
823 // =======================================================================
824 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
825                                                    const GLchar*                 theName,
826                                                    const OpenGl_Vec2i&           theValue)
827 {
828   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
829 }
830
831 // =======================================================================
832 // function : SetUniform
833 // purpose  : Specifies the value of the integer uniform 2D vector
834 // =======================================================================
835 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
836                                                    GLint                         theLocation,
837                                                    const OpenGl_Vec2i&           theValue)
838 {
839   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
840   {
841     return Standard_False;
842   }
843
844   theCtx->core20->glUniform2iv (theLocation, 1, theValue);
845   return Standard_True;
846 }
847
848 // =======================================================================
849 // function : SetUniform
850 // purpose  : Specifies the value of the integer uniform 3D vector
851 // =======================================================================
852 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
853                                                    const GLchar*                 theName,
854                                                    const OpenGl_Vec3i&           theValue)
855 {
856   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
857 }
858
859 // =======================================================================
860 // function : SetUniform
861 // purpose  : Specifies the value of the integer uniform 3D vector
862 // =======================================================================
863 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
864                                                    GLint                         theLocation,
865                                                    const OpenGl_Vec3i&           theValue)
866 {
867   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
868   {
869     return Standard_False;
870   }
871
872   theCtx->core20->glUniform3iv (theLocation, 1, theValue);
873   return Standard_True;
874 }
875
876 // =======================================================================
877 // function : SetUniform
878 // purpose  : Specifies the value of the integer uniform 4D vector
879 // =======================================================================
880 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
881                                                    const GLchar*                 theName,
882                                                    const OpenGl_Vec4i&           theValue)
883 {
884   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
885 }
886
887 // =======================================================================
888 // function : SetUniform
889 // purpose  : Specifies the value of the integer uniform 4D vector
890 // =======================================================================
891 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
892                                                    GLint                         theLocation,
893                                                    const OpenGl_Vec4i&           theValue)
894 {
895   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
896   {
897     return Standard_False;
898   }
899
900   theCtx->core20->glUniform4iv (theLocation, 1, theValue);
901   return Standard_True;
902 }
903
904 // =======================================================================
905 // function : SetUniform
906 // purpose  : Specifies the value of the floating-point uniform 2D vector
907 // =======================================================================
908 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
909                                                    const GLchar*                 theName,
910                                                    const OpenGl_Vec2&            theValue)
911 {
912   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
913 }
914
915 // =======================================================================
916 // function : SetUniform
917 // purpose  : Specifies the value of the floating-point uniform 2D vector
918 // =======================================================================
919 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
920                                                    GLint                         theLocation,
921                                                    const OpenGl_Vec2&            theValue)
922 {
923   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
924   {
925     return Standard_False;
926   }
927
928   theCtx->core20->glUniform2fv (theLocation, 1, theValue);
929   return Standard_True;
930 }
931
932 // =======================================================================
933 // function : SetUniform
934 // purpose  : Specifies the value of the floating-point uniform 3D vector
935 // =======================================================================
936 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
937                                                    const GLchar*                 theName,
938                                                    const OpenGl_Vec3&            theValue)
939 {
940   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
941 }
942
943 // =======================================================================
944 // function : SetUniform
945 // purpose  : Specifies the value of the floating-point uniform 3D vector
946 // =======================================================================
947 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
948                                                    GLint                         theLocation,
949                                                    const OpenGl_Vec3&            theValue)
950 {
951   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
952   {
953     return Standard_False;
954   }
955
956   theCtx->core20->glUniform3fv (theLocation, 1, theValue);
957   return Standard_True;
958 }
959
960 // =======================================================================
961 // function : SetUniform
962 // purpose  : Specifies the value of the floating-point uniform 4D vector
963 // =======================================================================
964 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
965                                                    const GLchar*                 theName,
966                                                    const OpenGl_Vec4&            theValue)
967 {
968   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
969 }
970
971 // =======================================================================
972 // function : SetUniform
973 // purpose  : Specifies the value of the floating-point uniform 4D vector
974 // =======================================================================
975 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
976                                                    GLint                         theLocation,
977                                                    const OpenGl_Vec4&            theValue)
978 {
979   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
980   {
981     return Standard_False;
982   }
983
984   theCtx->core20->glUniform4fv (theLocation, 1, theValue);
985   return Standard_True;
986 }
987
988 // =======================================================================
989 // function : SetUniform
990 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
991 // =======================================================================
992 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
993                                                    const GLchar*                 theName,
994                                                    const OpenGl_Matrix&          theValue,
995                                                    GLboolean                     theTranspose)
996 {
997   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
998 }
999
1000 // =======================================================================
1001 // function : SetUniform
1002 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1003 // =======================================================================
1004 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1005                                                    GLint                         theLocation,
1006                                                    const OpenGl_Matrix&          theValue,
1007                                                    GLboolean                     theTranspose)
1008 {
1009   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1010   {
1011     return Standard_False;
1012   }
1013
1014   theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue.mat);
1015   return Standard_True;
1016 }
1017
1018 // =======================================================================
1019 // function : SetUniform
1020 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1021 // =======================================================================
1022 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1023                                                    const GLchar*                 theName,
1024                                                    const Tmatrix3&               theValue,
1025                                                    GLboolean                     theTranspose)
1026 {
1027   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1028 }
1029
1030 // =======================================================================
1031 // function : SetUniform
1032 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1033 // =======================================================================
1034 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1035                                                    GLint                         theLocation,
1036                                                    const Tmatrix3&               theValue,
1037                                                    GLboolean                     theTranspose)
1038 {
1039   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1040   {
1041     return Standard_False;
1042   }
1043
1044   theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue);
1045   return Standard_True;
1046 }
1047
1048 // =======================================================================
1049 // function : SetSampler
1050 // purpose  : Specifies the value of the sampler uniform variable
1051 // =======================================================================
1052 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1053                                                    const GLchar*                 theName,
1054                                                    const GLenum                  theTextureUnit)
1055 {
1056   return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1057 }
1058
1059 // =======================================================================
1060 // function : SetSampler
1061 // purpose  : Specifies the value of the sampler uniform variable
1062 // =======================================================================
1063 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1064                                                    GLint                         theLocation,
1065                                                    const GLenum                  theTextureUnit)
1066 {
1067   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1068   {
1069     return Standard_False;
1070   }
1071
1072   theCtx->core20->glUniform1i (theLocation, theTextureUnit);
1073   return Standard_True;
1074 }
1075
1076 // =======================================================================
1077 // function : Create
1078 // purpose  : Creates new empty shader program of specified type
1079 // =======================================================================
1080 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1081 {
1082   if (myProgramID == NO_PROGRAM
1083    && theCtx->core20 != NULL)
1084   {
1085     myProgramID = theCtx->core20->glCreateProgram();
1086   }
1087
1088   return myProgramID != NO_PROGRAM;
1089 }
1090
1091 // =======================================================================
1092 // function : Release
1093 // purpose  : Destroys shader program
1094 // =======================================================================
1095 void OpenGl_ShaderProgram::Release (const OpenGl_Context* theCtx)
1096 {
1097   if (myProgramID == NO_PROGRAM)
1098   {
1099     return;
1100   }
1101
1102   Standard_ASSERT_RETURN (theCtx != NULL,
1103     "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1104
1105   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1106   {
1107     anIter.ChangeValue()->Release (theCtx);
1108     anIter.ChangeValue().Nullify();
1109   }
1110
1111   if (theCtx->core20 != NULL
1112    && theCtx->IsValid())
1113   {
1114     theCtx->core20->glDeleteProgram (myProgramID);
1115   }
1116
1117   myProgramID = NO_PROGRAM;
1118 }