0024192: Adding support for shaders to OCCT visualization toolkit
[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 {
243   memset (myCurrentState, 0, sizeof (myCurrentState));
244   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
245   {
246     myStateLocations[aVar] = INVALID_LOCATION;
247   }
248 }
249
250 // =======================================================================
251 // function : Initialize
252 // purpose  : Initializes program object with the list of shader objects
253 // =======================================================================
254 Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&     theCtx,
255                                                    const Graphic3d_ShaderObjectList& theShaders)
256 {
257   if (theCtx.IsNull() || !Create (theCtx))
258   {
259     return Standard_False;
260   }
261
262   GLchar *aShaderDir = getenv ("CSF_ShadersDirectory");
263   if (aShaderDir == NULL)
264   {
265     TCollection_ExtendedString aMsg = "Error! Failed to get OCCT shaders directory";
266
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
273     return Standard_False;
274   }
275
276   OSD_File aDeclFile (TCollection_AsciiString (aShaderDir) + "/Declarations.glsl");
277   if (!aDeclFile.Exists())
278   {
279     TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
280
281     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
282                          GL_DEBUG_TYPE_ERROR_ARB,
283                          0,
284                          GL_DEBUG_SEVERITY_HIGH_ARB,
285                          aMsg);
286
287     return Standard_False;
288   }
289
290   TCollection_AsciiString aDeclarations;
291
292   aDeclFile.Open (OSD_ReadOnly, OSD_Protection());
293   aDeclFile.Read (aDeclarations, aDeclFile.Size());
294   aDeclFile.Close();
295
296   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders);
297        anIter.More(); anIter.Next())
298   {
299     if (!anIter.Value()->IsDone())
300     {
301       TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
302
303       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
304                            GL_DEBUG_TYPE_ERROR_ARB,
305                            0,
306                            GL_DEBUG_SEVERITY_HIGH_ARB,
307                            aMsg);
308
309       return Standard_False;
310     }
311
312     Handle(OpenGl_ShaderObject) aShader;
313
314     // Note: Add support of other shader types here
315     switch (anIter.Value()->Type())
316     {
317       case Graphic3d_TOS_VERTEX:
318         aShader = new OpenGl_ShaderObject (GL_VERTEX_SHADER);
319         break;
320       case Graphic3d_TOS_FRAGMENT:
321         aShader = new OpenGl_ShaderObject (GL_FRAGMENT_SHADER);
322         break;
323     }
324
325     // Is unsupported shader type?
326     if (aShader.IsNull())
327     {
328       TCollection_ExtendedString aMsg = "Error! Unsupported shader type";
329
330       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
331                            GL_DEBUG_TYPE_ERROR_ARB,
332                            0,
333                            GL_DEBUG_SEVERITY_HIGH_ARB,
334                            aMsg);
335
336       return Standard_False;
337     }
338
339     if (!aShader->Create (theCtx))
340     {
341       return Standard_False;
342     }
343
344     TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
345     
346     if (anIter.Value()->Type() == Graphic3d_TOS_VERTEX)
347     {
348       aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
349     }
350
351     if (!aShader->LoadSource (theCtx, aSource))
352     {
353       TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
354
355       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
356                            GL_DEBUG_TYPE_ERROR_ARB,
357                            0,
358                            GL_DEBUG_SEVERITY_HIGH_ARB,
359                            aMsg);
360
361       return Standard_False;
362     }
363
364     if (!aShader->Compile (theCtx))
365     {
366       TCollection_ExtendedString aMsg = "Error! Failed to compile shader object";
367
368       theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
369                            GL_DEBUG_TYPE_ERROR_ARB,
370                            0,
371                            GL_DEBUG_SEVERITY_HIGH_ARB,
372                            aMsg);
373
374       if (theCtx->caps->contextDebug)
375       {
376         TCollection_AsciiString aLog;
377         aShader->FetchInfoLog (theCtx, aLog);
378         if (!aLog.IsEmpty())
379         {
380           std::cout << aLog.ToCString() << std::endl << std::flush;
381         }
382         else
383         {
384           std::cout << "Information log is empty" << std::endl;
385         }
386       }
387
388       return Standard_False;
389     }
390
391     if (!AttachShader (theCtx, aShader))
392     {
393       return Standard_False;
394     }
395   }
396
397   if (!Link (theCtx))
398   {
399     TCollection_ExtendedString aMsg = "Error! Failed to link program object";
400
401     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
402                          GL_DEBUG_TYPE_ERROR_ARB,
403                          0,
404                          GL_DEBUG_SEVERITY_HIGH_ARB,
405                          aMsg);
406
407     if (theCtx->caps->contextDebug)
408     {
409       TCollection_AsciiString aLog;
410       FetchInfoLog (theCtx, aLog);
411       if (!aLog.IsEmpty())
412       {
413         std::cout << aLog.ToCString() << std::endl;
414       }
415       else
416       {
417         std::cout << "Information log is empty" << std::endl;
418       }
419     }
420
421     return Standard_False;
422   }
423
424   return Standard_True;
425 }
426
427 // =======================================================================
428 // function : ~OpenGl_ShaderProgram
429 // purpose  : Releases resources of shader program
430 // =======================================================================
431 OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
432 {
433   Release (NULL);
434 }
435
436 // =======================================================================
437 // function : AttachShader
438 // purpose  : Attaches shader object to the program object
439 // =======================================================================
440 Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)&      theCtx,
441                                                      const Handle(OpenGl_ShaderObject)& theShader)
442 {
443   if (myProgramID == NO_PROGRAM || theShader.IsNull())
444   {
445     return Standard_False;
446   }
447
448   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
449   {
450     if (theShader == anIter.Value())
451     {
452       return Standard_False;
453     }
454   }
455
456   myShaderObjects.Append (theShader);
457   theCtx->core20->glAttachShader (myProgramID, theShader->myShaderID);
458   return Standard_True;
459 }
460
461 // =======================================================================
462 // function : DetachShader
463 // purpose  : Detaches shader object to the program object
464 // =======================================================================
465 Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)&      theCtx,
466                                                      const Handle(OpenGl_ShaderObject)& theShader)
467 {
468   if (myProgramID == NO_PROGRAM
469    || theShader.IsNull())
470   {
471     return Standard_False;
472   }
473
474   OpenGl_ShaderList::Iterator anIter (myShaderObjects);
475   while (anIter.More())
476   {
477     if (theShader == anIter.Value())
478     {
479       myShaderObjects.Remove (anIter);
480       break;
481     }
482
483     anIter.Next();
484   }
485
486   if (!anIter.More())
487   {
488     return Standard_False;
489   }
490
491   theCtx->core20->glDetachShader (myProgramID, theShader->myShaderID);
492   return Standard_True;
493 }
494
495 // =======================================================================
496 // function : Link
497 // purpose  : Links the program object
498 // =======================================================================
499 Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx)
500 {
501   if (myProgramID == NO_PROGRAM)
502   {
503     return Standard_False;
504   }
505
506   theCtx->core20->glLinkProgram (myProgramID);
507
508   GLint aStatus = GL_FALSE;
509   theCtx->core20->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
510
511   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
512   {
513     myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
514   }
515
516   return aStatus != GL_FALSE;
517 }
518
519 // =======================================================================
520 // function : FetchInfoLog
521 // purpose  : Fetches information log of the last link operation
522 // =======================================================================
523 Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
524                                                      TCollection_AsciiString&      theOutput)
525 {
526   if (myProgramID == NO_PROGRAM)
527   {
528     return Standard_False;
529   }
530
531   GLint aLength = 0;
532   theCtx->core20->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
533   if (aLength > 0)
534   {
535     GLchar* aLog = (GLchar*) alloca (aLength);
536     memset (aLog, 0, aLength);
537     theCtx->core20->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
538     theOutput = aLog;
539   }
540   return Standard_True;
541 }
542
543 // =======================================================================
544 // function : Bind
545 // purpose  : Sets the program object as part of current rendering state
546 // =======================================================================
547 void OpenGl_ShaderProgram::Bind (const Handle(OpenGl_Context)& theCtx) const
548 {
549   if (myProgramID == NO_PROGRAM)
550   {
551     return;
552   }
553
554   theCtx->core20->glUseProgram (myProgramID);
555   theCtx->ShaderManager()->myIsPP = Standard_True;
556 }
557
558 // =======================================================================
559 // function : ApplyVariables
560 // purpose  : Fetches uniform variables from proxy shader program
561 // =======================================================================
562 Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
563 {
564   if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
565   {
566     return Standard_False;
567   }
568
569   for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
570   {
571     mySetterSelector.Set (theCtx, anIter.Value(), this);
572   }
573
574   myProxy->ClearVariables();
575   return Standard_True;
576 }
577
578 // =======================================================================
579 // function : BindWithVariables
580 // purpose  : Binds the program object and applies variables
581 // =======================================================================
582 Standard_Boolean OpenGl_ShaderProgram::BindWithVariables (const Handle(OpenGl_Context)& theCtx)
583 {
584   Bind (theCtx);
585   return ApplyVariables (theCtx);
586 }
587
588 // =======================================================================
589 // function : Unbind
590 // purpose  : Reverts to fixed-function graphics pipeline (FFP)
591 // =======================================================================
592 void OpenGl_ShaderProgram::Unbind (const Handle(OpenGl_Context)& theCtx)
593 {
594   if (theCtx->ShaderManager()->myIsPP)
595   {
596     theCtx->core20->glUseProgram (NO_PROGRAM);
597     theCtx->ShaderManager()->myIsPP = Standard_False;
598   }
599 }
600
601 // =======================================================================
602 // function : ActiveState
603 // purpose  : Returns index of last modification for specified state type
604 // =======================================================================
605 Standard_Size OpenGl_ShaderProgram::ActiveState (const OpenGl_UniformStateType theType) const
606 {
607   if (theType < MaxStateTypes)
608   {
609     return myCurrentState[theType];
610   }
611   return 0;
612 }
613
614 // =======================================================================
615 // function : UpdateState
616 // purpose  : Updates index of last modification for specified state type
617 // =======================================================================
618 void OpenGl_ShaderProgram::UpdateState (const OpenGl_UniformStateType theType,
619                                         const Standard_Size           theIndex)
620 {
621   if (theType < MaxStateTypes)
622   {
623     myCurrentState[theType] = theIndex;
624   }
625 }
626
627 // =======================================================================
628 // function : GetUniformLocation
629 // purpose  : Returns location (index) of the specific uniform variable
630 // =======================================================================
631 GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
632                                                 const GLchar*                 theName) const
633 {
634   return myProgramID != NO_PROGRAM
635        ? theCtx->core20->glGetUniformLocation (myProgramID, theName)
636        : INVALID_LOCATION;
637 }
638
639 // =======================================================================
640 // function : GetAttributeLocation
641 // purpose  : Returns location (index) of the generic vertex attribute
642 // =======================================================================
643 GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
644                                                   const GLchar*                 theName) const
645 {
646   return myProgramID != NO_PROGRAM
647        ? theCtx->core20->glGetAttribLocation (myProgramID, theName)
648        : INVALID_LOCATION;
649 }
650
651 // =======================================================================
652 // function : GetStateLocation
653 // purpose  : Returns location of the OCCT state uniform variable
654 // =======================================================================
655 GLint OpenGl_ShaderProgram::GetStateLocation (const GLuint theVariable) const
656 {
657   if (theVariable < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES)
658   {
659     return myStateLocations[theVariable];
660   }
661   return INVALID_LOCATION;
662 }
663
664 // =======================================================================
665 // function : GetUniform
666 // purpose  : Returns the value of the integer uniform variable
667 // =======================================================================
668 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
669                                                    const GLchar*                 theName,
670                                                    OpenGl_Vec4i&                 theValue) const
671 {
672   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
673 }
674
675 // =======================================================================
676 // function : GetUniform
677 // purpose  : Returns the value of the integer uniform variable
678 // =======================================================================
679 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
680                                                    GLint                         theLocation,
681                                                    OpenGl_Vec4i&                 theValue) const
682 {
683   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
684   {
685     return Standard_False;
686   }
687
688   theCtx->core20->glGetUniformiv (myProgramID, theLocation, theValue);
689   return Standard_True;
690 }
691
692 // =======================================================================
693 // function : GetUniform
694 // purpose  : Returns the value of the floating-point uniform variable
695 // =======================================================================
696 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
697                                                    const GLchar*                 theName,
698                                                    OpenGl_Vec4&                  theValue) const
699 {
700   return GetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
701 }
702
703 // =======================================================================
704 // function : GetUniform
705 // purpose  : Returns the value of the floating-point uniform variable
706 // =======================================================================
707 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
708                                                    GLint                         theLocation,
709                                                    OpenGl_Vec4&                  theValue) const
710 {
711   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
712   {
713     return Standard_False;
714   }
715
716   theCtx->core20->glGetUniformfv (myProgramID, theLocation, theValue);
717   return Standard_True;
718 }
719
720 // =======================================================================
721 // function : GetAttribute
722 // purpose  : Returns the integer vertex attribute
723 // =======================================================================
724 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
725                                                      const GLchar*                 theName,
726                                                      OpenGl_Vec4i&                 theValue) const
727 {
728   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
729 }
730
731 // =======================================================================
732 // function : GetAttribute
733 // purpose  : Returns the integer vertex attribute
734 // =======================================================================
735 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
736                                                      GLint                         theIndex,
737                                                      OpenGl_Vec4i&                 theValue) const
738 {
739   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
740   {
741     return Standard_False;
742   }
743
744   theCtx->core20->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
745   return Standard_True;
746 }
747
748 // =======================================================================
749 // function : GetAttribute
750 // purpose  : Returns the floating-point vertex attribute
751 // =======================================================================
752 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
753                                                      const GLchar*                 theName,
754                                                      OpenGl_Vec4&                  theValue) const
755 {
756   return GetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
757 }
758
759 // =======================================================================
760 // function : GetAttribute
761 // purpose  : Returns the floating-point vertex attribute
762 // =======================================================================
763 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
764                                                      GLint                         theIndex,
765                                                      OpenGl_Vec4&                  theValue) const
766 {
767   if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
768   {
769     return Standard_False;
770   }
771
772   theCtx->core20->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
773   return Standard_True;
774 }
775
776 // =======================================================================
777 // function : SetUniform
778 // purpose  : Specifies the value of the integer uniform variable
779 // =======================================================================
780 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
781                                                    const GLchar*                 theName,
782                                                    GLint                         theValue)
783 {
784   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
785 }
786
787 // =======================================================================
788 // function : SetUniform
789 // purpose  : Specifies the value of the integer uniform variable
790 // =======================================================================
791 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
792                                                    GLint                         theLocation,
793                                                    GLint                         theValue)
794 {
795   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
796   {
797     return Standard_False;
798   }
799
800   theCtx->core20->glUniform1i (theLocation, theValue);
801   return Standard_True;
802 }
803
804 // =======================================================================
805 // function : SetUniform
806 // purpose  : Specifies the value of the floating-point uniform variable
807 // =======================================================================
808 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
809                                                    const GLchar*                 theName,
810                                                    GLfloat                       theValue)
811 {
812   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
813 }
814
815 // =======================================================================
816 // function : SetUniform
817 // purpose  : Specifies the value of the floating-point uniform variable
818 // =======================================================================
819 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
820                                                    GLint                         theLocation,
821                                                    GLfloat                       theValue)
822 {
823   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
824   {
825     return Standard_False;
826   }
827
828   theCtx->core20->glUniform1f (theLocation, theValue);
829   return Standard_True;
830 }
831
832 // =======================================================================
833 // function : SetUniform
834 // purpose  : Specifies the value of the integer uniform 2D vector
835 // =======================================================================
836 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
837                                                    const GLchar*                 theName,
838                                                    const OpenGl_Vec2i&           theValue)
839 {
840   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
841 }
842
843 // =======================================================================
844 // function : SetUniform
845 // purpose  : Specifies the value of the integer uniform 2D vector
846 // =======================================================================
847 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
848                                                    GLint                         theLocation,
849                                                    const OpenGl_Vec2i&           theValue)
850 {
851   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
852   {
853     return Standard_False;
854   }
855
856   theCtx->core20->glUniform2iv (theLocation, 1, theValue);
857   return Standard_True;
858 }
859
860 // =======================================================================
861 // function : SetUniform
862 // purpose  : Specifies the value of the integer uniform 3D vector
863 // =======================================================================
864 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
865                                                    const GLchar*                 theName,
866                                                    const OpenGl_Vec3i&           theValue)
867 {
868   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
869 }
870
871 // =======================================================================
872 // function : SetUniform
873 // purpose  : Specifies the value of the integer uniform 3D vector
874 // =======================================================================
875 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
876                                                    GLint                         theLocation,
877                                                    const OpenGl_Vec3i&           theValue)
878 {
879   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
880   {
881     return Standard_False;
882   }
883
884   theCtx->core20->glUniform3iv (theLocation, 1, theValue);
885   return Standard_True;
886 }
887
888 // =======================================================================
889 // function : SetUniform
890 // purpose  : Specifies the value of the integer uniform 4D vector
891 // =======================================================================
892 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
893                                                    const GLchar*                 theName,
894                                                    const OpenGl_Vec4i&           theValue)
895 {
896   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
897 }
898
899 // =======================================================================
900 // function : SetUniform
901 // purpose  : Specifies the value of the integer uniform 4D vector
902 // =======================================================================
903 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
904                                                    GLint                         theLocation,
905                                                    const OpenGl_Vec4i&           theValue)
906 {
907   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
908   {
909     return Standard_False;
910   }
911
912   theCtx->core20->glUniform4iv (theLocation, 1, theValue);
913   return Standard_True;
914 }
915
916 // =======================================================================
917 // function : SetUniform
918 // purpose  : Specifies the value of the floating-point uniform 2D vector
919 // =======================================================================
920 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
921                                                    const GLchar*                 theName,
922                                                    const OpenGl_Vec2&            theValue)
923 {
924   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
925 }
926
927 // =======================================================================
928 // function : SetUniform
929 // purpose  : Specifies the value of the floating-point uniform 2D vector
930 // =======================================================================
931 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
932                                                    GLint                         theLocation,
933                                                    const OpenGl_Vec2&            theValue)
934 {
935   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
936   {
937     return Standard_False;
938   }
939
940   theCtx->core20->glUniform2fv (theLocation, 1, theValue);
941   return Standard_True;
942 }
943
944 // =======================================================================
945 // function : SetUniform
946 // purpose  : Specifies the value of the floating-point uniform 3D vector
947 // =======================================================================
948 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
949                                                    const GLchar*                 theName,
950                                                    const OpenGl_Vec3&            theValue)
951 {
952   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
953 }
954
955 // =======================================================================
956 // function : SetUniform
957 // purpose  : Specifies the value of the floating-point uniform 3D vector
958 // =======================================================================
959 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
960                                                    GLint                         theLocation,
961                                                    const OpenGl_Vec3&            theValue)
962 {
963   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
964   {
965     return Standard_False;
966   }
967
968   theCtx->core20->glUniform3fv (theLocation, 1, theValue);
969   return Standard_True;
970 }
971
972 // =======================================================================
973 // function : SetUniform
974 // purpose  : Specifies the value of the floating-point uniform 4D vector
975 // =======================================================================
976 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
977                                                    const GLchar*                 theName,
978                                                    const OpenGl_Vec4&            theValue)
979 {
980   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
981 }
982
983 // =======================================================================
984 // function : SetUniform
985 // purpose  : Specifies the value of the floating-point uniform 4D vector
986 // =======================================================================
987 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
988                                                    GLint                         theLocation,
989                                                    const OpenGl_Vec4&            theValue)
990 {
991   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
992   {
993     return Standard_False;
994   }
995
996   theCtx->core20->glUniform4fv (theLocation, 1, theValue);
997   return Standard_True;
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                                                    const GLchar*                 theName,
1006                                                    const OpenGl_Matrix&          theValue,
1007                                                    GLboolean                     theTranspose)
1008 {
1009   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1010 }
1011
1012 // =======================================================================
1013 // function : SetUniform
1014 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1015 // =======================================================================
1016 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1017                                                    GLint                         theLocation,
1018                                                    const OpenGl_Matrix&          theValue,
1019                                                    GLboolean                     theTranspose)
1020 {
1021   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1022   {
1023     return Standard_False;
1024   }
1025
1026   theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue.mat);
1027   return Standard_True;
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                                                    const GLchar*                 theName,
1036                                                    const Tmatrix3&               theValue,
1037                                                    GLboolean                     theTranspose)
1038 {
1039   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
1040 }
1041
1042 // =======================================================================
1043 // function : SetUniform
1044 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
1045 // =======================================================================
1046 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1047                                                    GLint                         theLocation,
1048                                                    const Tmatrix3&               theValue,
1049                                                    GLboolean                     theTranspose)
1050 {
1051   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1052   {
1053     return Standard_False;
1054   }
1055
1056   theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue);
1057   return Standard_True;
1058 }
1059
1060 // =======================================================================
1061 // function : SetSampler
1062 // purpose  : Specifies the value of the sampler uniform variable
1063 // =======================================================================
1064 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1065                                                    const GLchar*                 theName,
1066                                                    const GLenum                  theTextureUnit)
1067 {
1068   return SetSampler (theCtx, GetUniformLocation (theCtx, theName), theTextureUnit);
1069 }
1070
1071 // =======================================================================
1072 // function : SetSampler
1073 // purpose  : Specifies the value of the sampler uniform variable
1074 // =======================================================================
1075 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1076                                                    GLint                         theLocation,
1077                                                    const GLenum                  theTextureUnit)
1078 {
1079   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1080   {
1081     return Standard_False;
1082   }
1083
1084   theCtx->core20->glUniform1i (theLocation, theTextureUnit);
1085   return Standard_True;
1086 }
1087
1088 // =======================================================================
1089 // function : Create
1090 // purpose  : Creates new empty shader program of specified type
1091 // =======================================================================
1092 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1093 {
1094   if (myProgramID == NO_PROGRAM
1095    && theCtx->core20 != NULL)
1096   {
1097     myProgramID = theCtx->core20->glCreateProgram();
1098   }
1099
1100   return myProgramID != NO_PROGRAM;
1101 }
1102
1103 // =======================================================================
1104 // function : Release
1105 // purpose  : Destroys shader program
1106 // =======================================================================
1107 void OpenGl_ShaderProgram::Release (const OpenGl_Context* theCtx)
1108 {
1109   if (myProgramID == NO_PROGRAM)
1110   {
1111     return;
1112   }
1113
1114   Standard_ASSERT_RETURN (theCtx != NULL,
1115     "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1116
1117   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1118   {
1119     anIter.ChangeValue()->Release (theCtx);
1120     anIter.ChangeValue().Nullify();
1121   }
1122
1123   if (theCtx->core20 != NULL)
1124   {
1125     theCtx->core20->glDeleteProgram (myProgramID);
1126   }
1127
1128   myProgramID = NO_PROGRAM;
1129 }