0027925: Visualization - implement order-independent transparency algorithm within...
[occt.git] / src / OpenGl / OpenGl_ShaderProgram.cxx
old mode 100644 (file)
new mode 100755 (executable)
index 7a7ffcd..7e3b8ad
@@ -1,25 +1,22 @@
 // Created on: 2013-09-19
 // Created by: Denis BOGOLEPOV
-// Copyright (c) 2013 OPEN CASCADE SAS
+// Copyright (c) 2013-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 #include <OSD_File.hxx>
 #include <OSD_Protection.hxx>
 
+#include <Graphic3d_Buffer.hxx>
 #include <Standard_Assert.hxx>
 #include <Standard_Atomic.hxx>
 #include <TCollection_ExtendedString.hxx>
 #include <OpenGl_Context.hxx>
 #include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_ShaderManager.hxx>
+#include <OpenGl_ArbTexBindless.hxx>
 
-IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource)
-IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource)
+#include <OpenGl_GlCore32.hxx>
+
+#include "../Shaders/Shaders_DeclarationsImpl_glsl.pxx"
+#include "../Shaders/Shaders_Declarations_glsl.pxx"
+
+#ifdef _WIN32
+  #include <malloc.h> // for alloca()
+#endif
+
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram,OpenGl_Resource)
 
 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
 
 // Declare OCCT-specific OpenGL/GLSL shader variables
 Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
 {
-  /* OpenGl_OCC_MODEL_WORLD_MATRIX */ "occModelWorldMatrix",
-  /* OpenGl_OCC_WORLD_VIEW_MATRIX */ "occWorldViewMatrix",
-  /* OpenGl_OCC_PROJECTION_MATRIX */ "occProjectionMatrix",
-  /* OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE */ "occModelWorldMatrixInverse",
-  /* OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE */ "occWorldViewMatrixInverse",
-  /* OpenGl_OCC_PROJECTION_MATRIX_INVERSE */ "occProjectionMatrixInverse",
-  /* OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE */ "occModelWorldMatrixTranspose",
-  /* OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE */ "occWorldViewMatrixTranspose",
-  /* OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE */ "occProjectionMatrixTranspose",
-  /* OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE */ "occModelWorldMatrixInverseTranspose",
-  /* OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE */ "occWorldViewMatrixInverseTranspose",
-  /* OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE */ "occProjectionMatrixInverseTranspose",
-
-  /* OpenGl_OCC_CLIP_PLANE_0_EQUATION */ "occClipPlanes[0].Equation",
-  /* OpenGl_OCC_CLIP_PLANE_1_EQUATION */ "occClipPlanes[1].Equation",
-  /* OpenGl_OCC_CLIP_PLANE_2_EQUATION */ "occClipPlanes[2].Equation",
-  /* OpenGl_OCC_CLIP_PLANE_3_EQUATION */ "occClipPlanes[3].Equation",
-  /* OpenGl_OCC_CLIP_PLANE_4_EQUATION */ "occClipPlanes[4].Equation",
-  /* OpenGl_OCC_CLIP_PLANE_5_EQUATION */ "occClipPlanes[5].Equation",
-  /* OpenGl_OCC_CLIP_PLANE_6_EQUATION */ "occClipPlanes[6].Equation",
-  /* OpenGl_OCC_CLIP_PLANE_7_EQUATION */ "occClipPlanes[7].Equation",
-
-  /* OpenGl_OCC_CLIP_PLANE_0_SPACE */ "occClipPlanes[0].Space",
-  /* OpenGl_OCC_CLIP_PLANE_1_SPACE */ "occClipPlanes[1].Space",
-  /* OpenGl_OCC_CLIP_PLANE_2_SPACE */ "occClipPlanes[2].Space",
-  /* OpenGl_OCC_CLIP_PLANE_3_SPACE */ "occClipPlanes[3].Space",
-  /* OpenGl_OCC_CLIP_PLANE_4_SPACE */ "occClipPlanes[4].Space",
-  /* OpenGl_OCC_CLIP_PLANE_5_SPACE */ "occClipPlanes[5].Space",
-  /* OpenGl_OCC_CLIP_PLANE_6_SPACE */ "occClipPlanes[6].Space",
-  /* OpenGl_OCC_CLIP_PLANE_7_SPACE */ "occClipPlanes[7].Space",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_COUNT */ "occLightSourcesCount",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_TYPE */ "occLightSources[0].Type",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_TYPE */ "occLightSources[1].Type",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_TYPE */ "occLightSources[2].Type",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_TYPE */ "occLightSources[3].Type",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_TYPE */ "occLightSources[4].Type",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_TYPE */ "occLightSources[5].Type",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_TYPE */ "occLightSources[6].Type",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_TYPE */ "occLightSources[7].Type",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_HEAD */ "occLightSources[0].Head",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_HEAD */ "occLightSources[1].Head",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_HEAD */ "occLightSources[2].Head",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_HEAD */ "occLightSources[3].Head",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_HEAD */ "occLightSources[4].Head",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_HEAD */ "occLightSources[5].Head",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_HEAD */ "occLightSources[6].Head",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_HEAD */ "occLightSources[7].Head",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_AMBIENT */ "occLightSources[0].Ambient",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_AMBIENT */ "occLightSources[1].Ambient",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_AMBIENT */ "occLightSources[2].Ambient",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_AMBIENT */ "occLightSources[3].Ambient",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_AMBIENT */ "occLightSources[4].Ambient",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_AMBIENT */ "occLightSources[5].Ambient",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_AMBIENT */ "occLightSources[6].Ambient",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_AMBIENT */ "occLightSources[7].Ambient",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_DIFFUSE */ "occLightSources[0].Diffuse",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_DIFFUSE */ "occLightSources[1].Diffuse",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_DIFFUSE */ "occLightSources[2].Diffuse",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_DIFFUSE */ "occLightSources[3].Diffuse",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_DIFFUSE */ "occLightSources[4].Diffuse",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_DIFFUSE */ "occLightSources[5].Diffuse",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_DIFFUSE */ "occLightSources[6].Diffuse",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_DIFFUSE */ "occLightSources[7].Diffuse",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_SPECULAR */ "occLightSources[0].Specular",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_SPECULAR */ "occLightSources[1].Specular",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_SPECULAR */ "occLightSources[2].Specular",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_SPECULAR */ "occLightSources[3].Specular",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_SPECULAR */ "occLightSources[4].Specular",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_SPECULAR */ "occLightSources[5].Specular",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_SPECULAR */ "occLightSources[6].Specular",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_SPECULAR */ "occLightSources[7].Specular",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_POSITION */ "occLightSources[0].Position",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_POSITION */ "occLightSources[1].Position",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_POSITION */ "occLightSources[2].Position",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_POSITION */ "occLightSources[3].Position",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_POSITION */ "occLightSources[4].Position",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_POSITION */ "occLightSources[5].Position",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_POSITION */ "occLightSources[6].Position",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_POSITION */ "occLightSources[7].Position",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_CUTOFF */ "occLightSources[0].SpotCutoff",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_CUTOFF */ "occLightSources[1].SpotCutoff",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_CUTOFF */ "occLightSources[2].SpotCutoff",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_CUTOFF */ "occLightSources[3].SpotCutoff",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_CUTOFF */ "occLightSources[4].SpotCutoff",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_CUTOFF */ "occLightSources[5].SpotCutoff",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_CUTOFF */ "occLightSources[6].SpotCutoff",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_CUTOFF */ "occLightSources[7].SpotCutoff",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_EXPONENT */ "occLightSources[0].SpotExponent",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_EXPONENT */ "occLightSources[1].SpotExponent",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_EXPONENT */ "occLightSources[2].SpotExponent",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_EXPONENT */ "occLightSources[3].SpotExponent",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_EXPONENT */ "occLightSources[4].SpotExponent",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_EXPONENT */ "occLightSources[5].SpotExponent",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_EXPONENT */ "occLightSources[6].SpotExponent",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_EXPONENT */ "occLightSources[7].SpotExponent",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_SPOT_DIRECTION */ "occLightSources[0].SpotDirection",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_SPOT_DIRECTION */ "occLightSources[1].SpotDirection",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_SPOT_DIRECTION */ "occLightSources[2].SpotDirection",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_SPOT_DIRECTION */ "occLightSources[3].SpotDirection",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_SPOT_DIRECTION */ "occLightSources[4].SpotDirection",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_SPOT_DIRECTION */ "occLightSources[5].SpotDirection",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_SPOT_DIRECTION */ "occLightSources[6].SpotDirection",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_SPOT_DIRECTION */ "occLightSources[7].SpotDirection",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_CONST_ATTENUATION */ "occLightSources[0].ConstAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_CONST_ATTENUATION */ "occLightSources[1].ConstAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_CONST_ATTENUATION */ "occLightSources[2].ConstAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_CONST_ATTENUATION */ "occLightSources[3].ConstAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_CONST_ATTENUATION */ "occLightSources[4].ConstAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_CONST_ATTENUATION */ "occLightSources[5].ConstAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_CONST_ATTENUATION */ "occLightSources[6].ConstAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_CONST_ATTENUATION */ "occLightSources[7].ConstAttenuation",
-
-  /* OpenGl_OCC_LIGHT_SOURCE_0_LINEAR_ATTENUATION */ "occLightSources[0].LinearAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_1_LINEAR_ATTENUATION */ "occLightSources[1].LinearAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_2_LINEAR_ATTENUATION */ "occLightSources[2].LinearAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_3_LINEAR_ATTENUATION */ "occLightSources[3].LinearAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_4_LINEAR_ATTENUATION */ "occLightSources[4].LinearAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_5_LINEAR_ATTENUATION */ "occLightSources[5].LinearAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_6_LINEAR_ATTENUATION */ "occLightSources[6].LinearAttenuation",
-  /* OpenGl_OCC_LIGHT_SOURCE_7_LINEAR_ATTENUATION */ "occLightSources[7].LinearAttenuation",
-
-  /* OpenGl_OCCT_ACTIVE_SAMPLER */ "occActiveSampler",
-  /* OpenGl_OCCT_TEXTURE_ENABLE */ "occTextureEnable",
-  /* OpenGl_OCCT_DISTINGUISH_MODE */ "occDistinguishingMode",
-  /* OpenGl_OCCT_FRONT_MATERIAL_AMBIENT */ "occFrontMaterial.Ambient",
-  /* OpenGl_OCCT_BACK_MATERIAL_AMBIENT */ "occBackMaterial.Ambient",
-  /* OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE */ "occFrontMaterial.Diffuse",
-  /* OpenGl_OCCT_BACK_MATERIAL_DIFFUSE */ "occBackMaterial.Diffuse",
-  /* OpenGl_OCCT_FRONT_MATERIAL_SPECULAR */ "occFrontMaterial.Specular",
-  /* OpenGl_OCCT_BACK_MATERIAL_SPECULAR */ "occBackMaterial.Specular",
-  /* OpenGl_OCCT_FRONT_MATERIAL_EMISSION */ "occFrontMaterial.Emission",
-  /* OpenGl_OCCT_BACK_MATERIAL_EMISSION */ "occBackMaterial.Emission",
-  /* OpenGl_OCCT_FRONT_MATERIAL_SHININESS */ "occFrontMaterial.Shininess",
-  /* OpenGl_OCCT_BACK_MATERIAL_SHININESS */ "occBackMaterial.Shininess",
-  /* OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY */ "occFrontMaterial.Transparency",
-  /* OpenGl_OCCT_BACK_MATERIAL_TRANSPARENCY */ "occBackMaterial.Transparency"
-
+  "occModelWorldMatrix",                 // OpenGl_OCC_MODEL_WORLD_MATRIX
+  "occWorldViewMatrix",                  // OpenGl_OCC_WORLD_VIEW_MATRIX
+  "occProjectionMatrix",                 // OpenGl_OCC_PROJECTION_MATRIX
+  "occModelWorldMatrixInverse",          // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE
+  "occWorldViewMatrixInverse",           // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE
+  "occProjectionMatrixInverse",          // OpenGl_OCC_PROJECTION_MATRIX_INVERSE
+  "occModelWorldMatrixTranspose",        // OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE
+  "occWorldViewMatrixTranspose",         // OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE
+  "occProjectionMatrixTranspose",        // OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE
+  "occModelWorldMatrixInverseTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE
+  "occWorldViewMatrixInverseTranspose",  // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
+  "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
+
+  "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
+  "occClipPlaneCount",     // OpenGl_OCC_CLIP_PLANE_COUNT
+
+  "occLightSourcesCount",  // OpenGl_OCC_LIGHT_SOURCE_COUNT
+  "occLightSourcesTypes",  // OpenGl_OCC_LIGHT_SOURCE_TYPES
+  "occLightSources",       // OpenGl_OCC_LIGHT_SOURCE_PARAMS
+  "occLightAmbient",       // OpenGl_OCC_LIGHT_AMBIENT
+
+  "occActiveSampler",      // OpenGl_OCCT_ACTIVE_SAMPLER
+  "occTextureEnable",      // OpenGl_OCCT_TEXTURE_ENABLE
+  "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
+  "occFrontMaterial",      // OpenGl_OCCT_FRONT_MATERIAL
+  "occBackMaterial",       // OpenGl_OCCT_BACK_MATERIAL
+  "occColor",              // OpenGl_OCCT_COLOR
+
+  "occOitOutput",          // OpenGl_OCCT_OIT_OUTPUT
+  "occOitDepthFactor",     // OpenGl_OCCT_OIT_DEPTH_FACTOR
+
+  "occTexTrsf2d",          // OpenGl_OCCT_TEXTURE_TRSF2D
+  "occPointSize"           // OpenGl_OCCT_POINT_SIZE
 };
 
 // =======================================================================
@@ -238,7 +129,8 @@ void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)&
 // =======================================================================
 OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
 : myProgramID (NO_PROGRAM),
-  myProxy     (theProxy)
+  myProxy     (theProxy),
+  myShareCount(1)
 {
   memset (myCurrentState, 0, sizeof (myCurrentState));
   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
@@ -259,53 +151,26 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  GLchar *aShaderDir = getenv ("CSF_ShadersDirectory");
-  if (aShaderDir == NULL)
-  {
-    TCollection_ExtendedString aMsg = "Error! Failed to get OCCT shaders directory";
-
-    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                         GL_DEBUG_TYPE_ERROR_ARB,
-                         0,
-                         GL_DEBUG_SEVERITY_HIGH_ARB,
-                         aMsg);
-
-    return Standard_False;
-  }
+  TCollection_AsciiString aHeader = !myProxy.IsNull() && !myProxy->Header().IsEmpty()
+                                  ? (myProxy->Header() + "\n")
+                                  : TCollection_AsciiString();
 
-  OSD_File aDeclFile (TCollection_AsciiString (aShaderDir) + "/Declarations.glsl");
-  if (!aDeclFile.Exists())
-  {
-    TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
+  TCollection_AsciiString aDeclarations = Shaders_Declarations_glsl;
+  TCollection_AsciiString aDeclImpl = Shaders_DeclarationsImpl_glsl;
 
-    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                         GL_DEBUG_TYPE_ERROR_ARB,
-                         0,
-                         GL_DEBUG_SEVERITY_HIGH_ARB,
-                         aMsg);
-
-    return Standard_False;
-  }
-
-  TCollection_AsciiString aDeclarations;
-
-  aDeclFile.Open (OSD_ReadOnly, OSD_Protection());
-  aDeclFile.Read (aDeclarations, (int)aDeclFile.Size());
-  aDeclFile.Close();
+  aDeclarations += aDeclImpl;
 
   for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders);
        anIter.More(); anIter.Next())
   {
     if (!anIter.Value()->IsDone())
     {
-      TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
-
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                           GL_DEBUG_TYPE_ERROR_ARB,
+      const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_ERROR,
                            0,
-                           GL_DEBUG_SEVERITY_HIGH_ARB,
+                           GL_DEBUG_SEVERITY_HIGH,
                            aMsg);
-
       return Standard_False;
     }
 
@@ -326,99 +191,185 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     if (aShader.IsNull())
     {
       TCollection_ExtendedString aMsg = "Error! Unsupported shader type";
-
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                           GL_DEBUG_TYPE_ERROR_ARB,
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_ERROR,
                            0,
-                           GL_DEBUG_SEVERITY_HIGH_ARB,
+                           GL_DEBUG_SEVERITY_HIGH,
                            aMsg);
-
       return Standard_False;
     }
 
     if (!aShader->Create (theCtx))
     {
+      aShader->Release (theCtx.operator->());
       return Standard_False;
     }
 
     TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
-    
-    if (anIter.Value()->Type() == Graphic3d_TOS_VERTEX)
+    TCollection_AsciiString anExtensions = "// This section enables extensions used in OCCT GLSL programs\n";
+    if (theCtx->hasDrawBuffers)
     {
-      aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
+      anExtensions += "#define OCC_ENABLE_draw_buffers\n";
+    }
+    if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions)
+    {
+      if (theCtx->arbDrawBuffers)
+      {
+        anExtensions += "#extension GL_ARB_draw_buffers : enable\n";
+      }
+      else if (theCtx->extDrawBuffers)
+      {
+        anExtensions += "#extension GL_EXT_draw_buffers : enable\n";
+      }
     }
 
-    if (!aShader->LoadSource (theCtx, aSource))
+    if (theCtx->hasSampleVariables == OpenGl_FeatureInExtensions)
+    {
+#if defined(GL_ES_VERSION_2_0)
+      if (theCtx->oesSampleVariables)
+      {
+        anExtensions += "#extension GL_OES_sample_variables : enable\n";
+      }
+#else
+      if (theCtx->arbSampleShading)
+      {
+        anExtensions += "#extension GL_ARB_sample_shading : enable\n";
+      }
+#endif
+    }
+
+    switch (anIter.Value()->Type())
     {
-      TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
+      case Graphic3d_TOS_VERTEX:
+      {
+        aSource = aHeader + TCollection_AsciiString ("#define VERTEX_SHADER\n") + anExtensions + aSource;
+        break;
+      }
+      case Graphic3d_TOS_FRAGMENT:
+      {
+      #if defined(GL_ES_VERSION_2_0)
+        TCollection_AsciiString aPrefix (theCtx->hasHighp
+                                       ? "precision highp float;\n"
+                                         "precision highp int;\n"
+                                       : "precision mediump float;\n"
+                                         "precision mediump int;\n");
+        aSource = aHeader + aPrefix + anExtensions + aSource;
+      #else
+        aSource = aHeader + anExtensions + aSource;
+      #endif
+        break;
+      }
+    }
 
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                           GL_DEBUG_TYPE_ERROR_ARB,
+    if (!aShader->LoadSource (theCtx, aSource))
+    {
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aSource);
+      const TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_ERROR,
                            0,
-                           GL_DEBUG_SEVERITY_HIGH_ARB,
+                           GL_DEBUG_SEVERITY_HIGH,
                            aMsg);
-
+      aShader->Release (theCtx.operator->());
       return Standard_False;
     }
 
     if (!aShader->Compile (theCtx))
     {
-      TCollection_ExtendedString aMsg = "Error! Failed to compile shader object";
-
-      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                           GL_DEBUG_TYPE_ERROR_ARB,
-                           0,
-                           GL_DEBUG_SEVERITY_HIGH_ARB,
-                           aMsg);
-
-      if (theCtx->caps->contextDebug)
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aSource);
+      TCollection_AsciiString aLog;
+      aShader->FetchInfoLog (theCtx, aLog);
+      if (aLog.IsEmpty())
       {
-        TCollection_AsciiString aLog;
-        aShader->FetchInfoLog (theCtx, aLog);
-        if (!aLog.IsEmpty())
-        {
-          std::cout << aLog.ToCString() << std::endl << std::flush;
-        }
-        else
-        {
-          std::cout << "Information log is empty" << std::endl;
-        }
+        aLog = "Compilation log is empty.";
       }
-
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_ERROR,
+                           0,
+                           GL_DEBUG_SEVERITY_HIGH,
+                           TCollection_ExtendedString ("Failed to compile shader object. Compilation log:\n") + aLog);
+      aShader->Release (theCtx.operator->());
       return Standard_False;
     }
+    else if (theCtx->caps->glslWarnings)
+    {
+      TCollection_AsciiString aLog;
+      aShader->FetchInfoLog (theCtx, aLog);
+      if (!aLog.IsEmpty()
+       && !aLog.IsEqual ("No errors.\n"))
+      {
+        theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                             GL_DEBUG_TYPE_PORTABILITY,
+                             0,
+                             GL_DEBUG_SEVERITY_LOW,
+                             TCollection_ExtendedString ("Shader compilation log:\n") + aLog);
+      }
+    }
 
     if (!AttachShader (theCtx, aShader))
     {
+      aShader->Release (theCtx.operator->());
       return Standard_False;
     }
   }
 
-  if (!Link (theCtx))
+  // bind locations for pre-defined Vertex Attributes
+  SetAttributeName (theCtx, Graphic3d_TOA_POS,   "occVertex");
+  SetAttributeName (theCtx, Graphic3d_TOA_NORM,  "occNormal");
+  SetAttributeName (theCtx, Graphic3d_TOA_UV,    "occTexCoord");
+  SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occVertColor");
+
+  // bind custom Vertex Attributes
+  if (!myProxy.IsNull())
   {
-    TCollection_ExtendedString aMsg = "Error! Failed to link program object";
+    for (Graphic3d_ShaderAttributeList::Iterator anAttribIter (myProxy->VertexAttributes());
+         anAttribIter.More(); anAttribIter.Next())
+    {
+      SetAttributeName (theCtx, anAttribIter.Value()->Location(), anAttribIter.Value()->Name().ToCString());
+    }
+  }
 
-    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-                         GL_DEBUG_TYPE_ERROR_ARB,
+  if (!Link (theCtx))
+  {
+    TCollection_AsciiString aLog;
+    FetchInfoLog (theCtx, aLog);
+    if (aLog.IsEmpty())
+    {
+      aLog = "Linker log is empty.";
+    }
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                         GL_DEBUG_TYPE_ERROR,
                          0,
-                         GL_DEBUG_SEVERITY_HIGH_ARB,
-                         aMsg);
-
-    if (theCtx->caps->contextDebug)
+                         GL_DEBUG_SEVERITY_HIGH,
+                         TCollection_ExtendedString ("Failed to link program object! Linker log:\n") + aLog);
+    return Standard_False;
+  }
+  else if (theCtx->caps->glslWarnings)
+  {
+    TCollection_AsciiString aLog;
+    FetchInfoLog (theCtx, aLog);
+    if (!aLog.IsEmpty()
+     && !aLog.IsEqual ("No errors.\n"))
     {
-      TCollection_AsciiString aLog;
-      FetchInfoLog (theCtx, aLog);
-      if (!aLog.IsEmpty())
-      {
-        std::cout << aLog.ToCString() << std::endl;
-      }
-      else
-      {
-        std::cout << "Information log is empty" << std::endl;
-      }
+      theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                           GL_DEBUG_TYPE_PORTABILITY,
+                           0,
+                           GL_DEBUG_SEVERITY_LOW,
+                           TCollection_ExtendedString ("GLSL linker log:\n") + aLog);
     }
+  }
 
-    return Standard_False;
+  // set uniform defaults
+  const GLint aLocSampler   = GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER);
+  const GLint aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE);
+  if (aLocSampler   != INVALID_LOCATION
+   || aLocTexEnable != INVALID_LOCATION)
+  {
+    const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
+    theCtx->core20fwd->glUseProgram (myProgramID);
+    SetUniform (theCtx, aLocSampler,   0); // GL_TEXTURE0
+    SetUniform (theCtx, aLocTexEnable, 0); // Off
+    theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
   }
 
   return Standard_True;
@@ -454,7 +405,7 @@ Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context
   }
 
   myShaderObjects.Append (theShader);
-  theCtx->core20->glAttachShader (myProgramID, theShader->myShaderID);
+  theCtx->core20fwd->glAttachShader (myProgramID, theShader->myShaderID);
   return Standard_True;
 }
 
@@ -488,7 +439,7 @@ Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context
     return Standard_False;
   }
 
-  theCtx->core20->glDetachShader (myProgramID, theShader->myShaderID);
+  theCtx->core20fwd->glDetachShader (myProgramID, theShader->myShaderID);
   return Standard_True;
 }
 
@@ -503,17 +454,19 @@ Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCt
     return Standard_False;
   }
 
-  theCtx->core20->glLinkProgram (myProgramID);
-
   GLint aStatus = GL_FALSE;
-  theCtx->core20->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
+  theCtx->core20fwd->glLinkProgram (myProgramID);
+  theCtx->core20fwd->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
+  if (aStatus == GL_FALSE)
+  {
+    return Standard_False;
+  }
 
   for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
   {
     myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
   }
-
-  return aStatus != GL_FALSE;
+  return Standard_True;
 }
 
 // =======================================================================
@@ -529,32 +482,17 @@ Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context
   }
 
   GLint aLength = 0;
-  theCtx->core20->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
+  theCtx->core20fwd->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
   if (aLength > 0)
   {
     GLchar* aLog = (GLchar*) alloca (aLength);
     memset (aLog, 0, aLength);
-    theCtx->core20->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
+    theCtx->core20fwd->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
     theOutput = aLog;
   }
   return Standard_True;
 }
 
-// =======================================================================
-// function : Bind
-// purpose  : Sets the program object as part of current rendering state
-// =======================================================================
-void OpenGl_ShaderProgram::Bind (const Handle(OpenGl_Context)& theCtx) const
-{
-  if (myProgramID == NO_PROGRAM)
-  {
-    return;
-  }
-
-  theCtx->core20->glUseProgram (myProgramID);
-  theCtx->ShaderManager()->myIsPP = Standard_True;
-}
-
 // =======================================================================
 // function : ApplyVariables
 // purpose  : Fetches uniform variables from proxy shader program
@@ -575,55 +513,6 @@ Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Contex
   return Standard_True;
 }
 
-// =======================================================================
-// function : BindWithVariables
-// purpose  : Binds the program object and applies variables
-// =======================================================================
-Standard_Boolean OpenGl_ShaderProgram::BindWithVariables (const Handle(OpenGl_Context)& theCtx)
-{
-  Bind (theCtx);
-  return ApplyVariables (theCtx);
-}
-
-// =======================================================================
-// function : Unbind
-// purpose  : Reverts to fixed-function graphics pipeline (FFP)
-// =======================================================================
-void OpenGl_ShaderProgram::Unbind (const Handle(OpenGl_Context)& theCtx)
-{
-  if (theCtx->ShaderManager()->myIsPP)
-  {
-    theCtx->core20->glUseProgram (NO_PROGRAM);
-    theCtx->ShaderManager()->myIsPP = Standard_False;
-  }
-}
-
-// =======================================================================
-// function : ActiveState
-// purpose  : Returns index of last modification for specified state type
-// =======================================================================
-Standard_Size OpenGl_ShaderProgram::ActiveState (const OpenGl_UniformStateType theType) const
-{
-  if (theType < MaxStateTypes)
-  {
-    return myCurrentState[theType];
-  }
-  return 0;
-}
-
-// =======================================================================
-// function : UpdateState
-// purpose  : Updates index of last modification for specified state type
-// =======================================================================
-void OpenGl_ShaderProgram::UpdateState (const OpenGl_UniformStateType theType,
-                                        const Standard_Size           theIndex)
-{
-  if (theType < MaxStateTypes)
-  {
-    myCurrentState[theType] = theIndex;
-  }
-}
-
 // =======================================================================
 // function : GetUniformLocation
 // purpose  : Returns location (index) of the specific uniform variable
@@ -632,7 +521,7 @@ GLint OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& th
                                                 const GLchar*                 theName) const
 {
   return myProgramID != NO_PROGRAM
-       ? theCtx->core20->glGetUniformLocation (myProgramID, theName)
+       ? theCtx->core20fwd->glGetUniformLocation (myProgramID, theName)
        : INVALID_LOCATION;
 }
 
@@ -644,7 +533,7 @@ GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)&
                                                   const GLchar*                 theName) const
 {
   return myProgramID != NO_PROGRAM
-       ? theCtx->core20->glGetAttribLocation (myProgramID, theName)
+       ? theCtx->core20fwd->glGetAttribLocation (myProgramID, theName)
        : INVALID_LOCATION;
 }
 
@@ -685,7 +574,7 @@ Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glGetUniformiv (myProgramID, theLocation, theValue);
+  theCtx->core20fwd->glGetUniformiv (myProgramID, theLocation, theValue);
   return Standard_True;
 }
 
@@ -713,7 +602,7 @@ Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glGetUniformfv (myProgramID, theLocation, theValue);
+  theCtx->core20fwd->glGetUniformfv (myProgramID, theLocation, theValue);
   return Standard_True;
 }
 
@@ -741,7 +630,7 @@ Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context
     return Standard_False;
   }
 
-  theCtx->core20->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
+  theCtx->core20fwd->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
   return Standard_True;
 }
 
@@ -769,7 +658,131 @@ Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context
     return Standard_False;
   }
 
-  theCtx->core20->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
+  theCtx->core20fwd->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetAttributeName
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Context)& theCtx,
+                                                         GLint                         theIndex,
+                                                         const GLchar*                 theName)
+{
+  theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetAttribute
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
+                                                     const GLchar*                 theName,
+                                                     GLfloat                       theValue)
+{
+  return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
+}
+
+// =======================================================================
+// function : SetAttribute
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
+                                                     GLint                         theIndex,
+                                                     GLfloat                       theValue)
+{
+  if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glVertexAttrib1f (theIndex, theValue);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetAttribute
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
+                                                     const GLchar*                 theName,
+                                                     const OpenGl_Vec2&            theValue)
+{
+  return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
+}
+
+// =======================================================================
+// function : SetAttribute
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
+                                                     GLint                         theIndex,
+                                                     const OpenGl_Vec2&            theValue)
+{
+  if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glVertexAttrib2fv (theIndex, theValue);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetAttribute
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
+                                                     const GLchar*                 theName,
+                                                     const OpenGl_Vec3&            theValue)
+{
+  return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
+}
+
+// =======================================================================
+// function : SetAttribute
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
+                                                     GLint                         theIndex,
+                                                     const OpenGl_Vec3&            theValue)
+{
+  if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glVertexAttrib3fv (theIndex, theValue);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetAttribute
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
+                                                     const GLchar*                 theName,
+                                                     const OpenGl_Vec4&            theValue)
+{
+  return SetAttribute (theCtx, GetAttributeLocation (theCtx, theName), theValue);
+}
+
+// =======================================================================
+// function : SetAttribute
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
+                                                     GLint                         theIndex,
+                                                     const OpenGl_Vec4&            theValue)
+{
+  if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glVertexAttrib4fv (theIndex, theValue);
   return Standard_True;
 }
 
@@ -797,8 +810,77 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniform1i (theLocation, theValue);
+  theCtx->core20fwd->glUniform1i (theLocation, theValue);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   const GLchar*                 theName,
+                                                   const OpenGl_Vec2u&           theValue)
+{
+  return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   const OpenGl_Vec2u&           theValue)
+{
+  if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+#if !defined(GL_ES_VERSION_2_0)
+  theCtx->core32->glUniform2uiv (theLocation, 1, theValue.GetData());
   return Standard_True;
+#else
+  (void )theValue;
+  return Standard_False;
+#endif
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   const GLchar*                 theName,
+                                                   const GLsizei                 theCount,
+                                                   const OpenGl_Vec2u*           theValue)
+{
+  return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue);
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   const GLsizei                 theCount,
+                                                   const OpenGl_Vec2u*           theValue)
+{
+  if (theCtx->core32 == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+#if !defined(GL_ES_VERSION_2_0)
+  theCtx->core32->glUniform2uiv (theLocation, theCount, theValue->GetData());
+  return Standard_True;
+#else
+  (void )theCount;
+  (void )theValue;
+  return Standard_False;
+#endif
 }
 
 // =======================================================================
@@ -825,7 +907,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniform1f (theLocation, theValue);
+  theCtx->core20fwd->glUniform1f (theLocation, theValue);
   return Standard_True;
 }
 
@@ -853,7 +935,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniform2iv (theLocation, 1, theValue);
+  theCtx->core20fwd->glUniform2iv (theLocation, 1, theValue);
   return Standard_True;
 }
 
@@ -881,7 +963,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniform3iv (theLocation, 1, theValue);
+  theCtx->core20fwd->glUniform3iv (theLocation, 1, theValue);
   return Standard_True;
 }
 
@@ -909,7 +991,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniform4iv (theLocation, 1, theValue);
+  theCtx->core20fwd->glUniform4iv (theLocation, 1, theValue);
   return Standard_True;
 }
 
@@ -937,7 +1019,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniform2fv (theLocation, 1, theValue);
+  theCtx->core20fwd->glUniform2fv (theLocation, 1, theValue);
   return Standard_True;
 }
 
@@ -965,7 +1047,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniform3fv (theLocation, 1, theValue);
+  theCtx->core20fwd->glUniform3fv (theLocation, 1, theValue);
   return Standard_True;
 }
 
@@ -993,7 +1075,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniform4fv (theLocation, 1, theValue);
+  theCtx->core20fwd->glUniform4fv (theLocation, 1, theValue);
   return Standard_True;
 }
 
@@ -1003,7 +1085,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
                                                    const GLchar*                 theName,
-                                                   const OpenGl_Matrix&          theValue,
+                                                   const OpenGl_Mat4&            theValue,
                                                    GLboolean                     theTranspose)
 {
   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
@@ -1015,7 +1097,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
                                                    GLint                         theLocation,
-                                                   const OpenGl_Matrix&          theValue,
+                                                   const OpenGl_Mat4&            theValue,
                                                    GLboolean                     theTranspose)
 {
   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
@@ -1023,7 +1105,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue.mat);
+  theCtx->core20fwd->glUniformMatrix4fv (theLocation, 1, GL_FALSE, theTranspose ? theValue.Transposed() : theValue);
   return Standard_True;
 }
 
@@ -1033,7 +1115,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
                                                    const GLchar*                 theName,
-                                                   const Tmatrix3&               theValue,
+                                                   const OpenGl_Matrix&          theValue,
                                                    GLboolean                     theTranspose)
 {
   return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
@@ -1045,15 +1127,153 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
 // =======================================================================
 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
                                                    GLint                         theLocation,
-                                                   const Tmatrix3&               theValue,
+                                                   const OpenGl_Matrix&          theValue,
                                                    GLboolean                     theTranspose)
+{
+  return SetUniform (theCtx, theLocation, OpenGl_Mat4::Map (*theValue.mat), theTranspose);
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the float uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   GLuint                        theCount,
+                                                   const Standard_ShortReal*     theData)
+{
+  if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glUniform1fv (theLocation, theCount, theData);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the float2 uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   GLuint                        theCount,
+                                                   const OpenGl_Vec2*            theData)
+{
+  if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glUniform2fv (theLocation, theCount, theData[0].GetData());
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the float3 uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   GLuint                        theCount,
+                                                   const OpenGl_Vec3*            theData)
+{
+  if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glUniform3fv (theLocation, theCount, theData[0].GetData());
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the float4 uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   GLuint                        theCount,
+                                                   const OpenGl_Vec4*            theData)
+{
+  if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glUniform4fv (theLocation, theCount, theData[0].GetData());
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the integer uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   GLuint                        theCount,
+                                                   const Standard_Integer*       theData)
 {
   if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
   {
     return Standard_False;
   }
 
-  theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, *theValue);
+  theCtx->core20fwd->glUniform1iv (theLocation, theCount, theData);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the int2 uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   GLuint                        theCount,
+                                                   const OpenGl_Vec2i*           theData)
+{
+  if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glUniform2iv (theLocation, theCount, theData[0].GetData());
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the int3 uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   GLuint                        theCount,
+                                                   const OpenGl_Vec3i*           theData)
+{
+  if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glUniform3iv (theLocation, theCount, theData[0].GetData());
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the int4 uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   GLuint                        theCount,
+                                                   const OpenGl_Vec4i*           theData)
+{
+  if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20fwd->glUniform4iv (theLocation, theCount, theData[0].GetData());
   return Standard_True;
 }
 
@@ -1081,7 +1301,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)&
     return Standard_False;
   }
 
-  theCtx->core20->glUniform1i (theLocation, theTextureUnit);
+  theCtx->core20fwd->glUniform1i (theLocation, theTextureUnit);
   return Standard_True;
 }
 
@@ -1092,9 +1312,9 @@ Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)&
 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
 {
   if (myProgramID == NO_PROGRAM
-   && theCtx->core20 != NULL)
+   && theCtx->core20fwd != NULL)
   {
-    myProgramID = theCtx->core20->glCreateProgram();
+    myProgramID = theCtx->core20fwd->glCreateProgram();
   }
 
   return myProgramID != NO_PROGRAM;
@@ -1104,7 +1324,7 @@ Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& the
 // function : Release
 // purpose  : Destroys shader program
 // =======================================================================
-void OpenGl_ShaderProgram::Release (const OpenGl_Context* theCtx)
+void OpenGl_ShaderProgram::Release (OpenGl_Context* theCtx)
 {
   if (myProgramID == NO_PROGRAM)
   {
@@ -1116,13 +1336,17 @@ void OpenGl_ShaderProgram::Release (const OpenGl_Context* theCtx)
 
   for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
   {
-    anIter.ChangeValue()->Release (theCtx);
-    anIter.ChangeValue().Nullify();
+    if (!anIter.Value().IsNull())
+    {
+      anIter.ChangeValue()->Release (theCtx);
+      anIter.ChangeValue().Nullify();
+    }
   }
 
-  if (theCtx->core20 != NULL)
+  if (theCtx->core20fwd != NULL
+   && theCtx->IsValid())
   {
-    theCtx->core20->glDeleteProgram (myProgramID);
+    theCtx->core20fwd->glDeleteProgram (myProgramID);
   }
 
   myProgramID = NO_PROGRAM;