Back to index

nux  3.0.0
IOpenGLGLSLShader.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2010 Inalogic® Inc.
00003  *
00004  * This program is free software: you can redistribute it and/or modify it
00005  * under the terms of the GNU Lesser General Public License, as
00006  * published by the  Free Software Foundation; either version 2.1 or 3.0
00007  * of the License.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranties of
00011  * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
00012  * PURPOSE.  See the applicable version of the GNU Lesser General Public
00013  * License for more details.
00014  *
00015  * You should have received a copy of both the GNU Lesser General Public
00016  * License along with this program. If not, see <http://www.gnu.org/licenses/>
00017  *
00018  * Authored by: Jay Taoko <jaytaoko@inalogic.com>
00019  *
00020  */
00021 
00022 #include "GLResource.h"
00023 #include "GraphicsDisplay.h"
00024 #include "GpuDevice.h"
00025 #include "GLDeviceObjects.h"
00026 #include "IOpenGLGLSLShader.h"
00027 
00028 namespace nux
00029 {
00030   namespace local
00031   {
00032   namespace
00033   {
00034     GLuint last_loaded_shader = 0;
00035     bool enable_tracking = false;
00036   }
00037   }
00038 
00039   NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLShader);
00040   NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLVertexShader);
00041   NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLPixelShader);
00042   //NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLGeometryShader);
00043   NUX_IMPLEMENT_OBJECT_TYPE(IOpenGLShaderProgram);
00044 
00045 
00046   bool ExtractShaderString3(const NString &ShaderToken, const NString &ShaderSource, NString &RetSource, NString ShaderPreprocessorDefines)
00047   {
00048     size_t lineStart = 0;
00049     size_t lineCount = 1;
00050     bool startTokenFound = false;
00051     size_t shaderStringStart = 0;
00052     size_t shaderStartLine   = 1;
00053 
00054 
00055     //Loop for all characters in the string
00056     if (ShaderToken != "")
00057     {
00058       size_t i;
00059 
00060       for (i = 0; i < ShaderSource.Length(); i++)
00061       {
00062         //Check if the starting character '[' (open bracket) is found at the beginning of the line
00063         // i counts the characters in the file. lineStart is equal to i at the beginning of the line.
00064         if ((TCharStringNCompare(&ShaderSource[i], "[", 1) == 0) && (lineStart == i))
00065         {
00066           if (!startTokenFound)
00067           {
00068             //Test for the start token
00069             if (ShaderSource.FindFirstOccurence(ShaderToken) == i)
00070             {
00071               // Found the shader token
00072               shaderStringStart = i + ShaderToken.Length();
00073               startTokenFound = true;
00074 
00075               //Set what line the shader was found on
00076               shaderStartLine = lineCount;
00077             }
00078           }
00079           else
00080           {
00081             //Break where the end token was found
00082             break;
00083           }
00084         }
00085 
00086         //If the character is equal to the new line character,
00087         // The next character must be on the new line
00088         if ((TCharStringNCompare(&ShaderSource[i], "\r", 1) == 0) || (TCharStringNCompare(&ShaderSource[i], "\n", 1) == 0))
00089         {
00090           lineStart = i + 1;
00091         }
00092 
00093         //Count the new lines
00094         if (TCharStringNCompare(&ShaderSource[i], "\n", 1) == 0)
00095         {
00096           lineCount++;
00097         }
00098       }
00099 
00100       //If the string was not found, return false
00101       if (!startTokenFound || shaderStringStart >= i)
00102       {
00103         return false;
00104       }
00105 
00106       //Assign the return string
00107       RetSource = ShaderSource.GetSubString(shaderStringStart, i - shaderStringStart);
00108 
00109       //Add the line directive to the shader source. See the documentation for GLSL #line directive.
00110       // GLSL spec: The #version directive must occur in a shader before anything else, except for comments and white space.
00111       size_t Pos = RetSource.FindFirstOccurence("#version");
00112 
00113       while (RetSource[Pos] != '\n')
00114       {
00115         if (RetSource[Pos] == 0)
00116           break;
00117 
00118         ++Pos;
00119       }
00120 
00121       if (RetSource[Pos] != 0)
00122         ++Pos;
00123 
00124       size_t EndOfLinePosition = 0;
00125       size_t LinePosition = 0;
00126 
00127       while ((EndOfLinePosition = RetSource.FindNextOccurence('\n', EndOfLinePosition)) < Pos - 1)
00128       {
00129         ++EndOfLinePosition;
00130         ++LinePosition;
00131       }
00132 
00133       RetSource.Insert(Pos, NString::Printf("#line %u\n", LinePosition + shaderStartLine));
00134 
00135       // Insert the preprocessor definitions before the #line directive
00136       if (ShaderPreprocessorDefines.Length())
00137         RetSource.Insert(Pos, ShaderPreprocessorDefines + NString('\n'));
00138 
00139       return true;
00140     }
00141     else
00142     {
00143       // We are not searching for a start token. Return the whole source.
00144       RetSource = ShaderSource;
00145       return true;
00146     }
00147   }
00148 
00149   static void InsertPreProcessorDefinitions(const NString &ShaderSource, NString &RetSource, NString &ShaderPreprocessorDefines)
00150   {
00151     RetSource = ShaderSource;
00152 
00153     if (ShaderPreprocessorDefines.Length() == 0)
00154       return;
00155 
00156     // GLSL spec: The #version directive must occur in a shader before anything else, except for comments and white space.
00157     size_t Pos = RetSource.FindFirstOccurence("#version");
00158 
00159     if (Pos != tstring::npos)
00160     {
00161       Pos = RetSource.FindNextOccurence('\n', Pos);
00162 
00163       if (Pos == tstring::npos)
00164       {
00165         // this is most likely an incorrect shader
00166         Pos = RetSource.Size();
00167         RetSource.Insert(Pos, NString('\n'));
00168         Pos = RetSource.Size();
00169       }
00170       else
00171       {
00172         // Skip character \n
00173         Pos++;
00174       }
00175     }
00176     else
00177     {
00178       Pos = 0;
00179     }
00180 
00181     if (ShaderPreprocessorDefines.Length())
00182       RetSource.Insert(Pos, ShaderPreprocessorDefines + NString('\n'));
00183   }
00184 
00185   IOpenGLShader::IOpenGLShader(NString ShaderName, OpenGLResourceType ResourceType)
00186     :   IOpenGLResource(ResourceType)
00187     ,   _ShaderName(ShaderName)
00188   {
00189 
00190   }
00191 
00192   IOpenGLShader::~IOpenGLShader()
00193   {
00194 
00195   }
00196 
00197   IOpenGLVertexShader::IOpenGLVertexShader(NString ShaderName)
00198     :   IOpenGLShader(ShaderName, RT_GLSL_VERTEXSHADER)
00199     ,   m_CompiledAndReady(false)
00200   {
00201     _OpenGLID = glCreateShader(GL_VERTEX_SHADER_ARB);
00202     CHECKGL_MSG( glCreateShader(GL_VERTEX_SHADER_ARB));
00203   }
00204 
00205   IOpenGLVertexShader::~IOpenGLVertexShader()
00206   {
00207     CHECKGL(glDeleteShader(_OpenGLID));
00208     _OpenGLID = 0;
00209     m_CompiledAndReady = false;
00210   }
00211 
00212   void IOpenGLVertexShader::SetShaderCode(const char *ShaderCode, const char *VtxShaderPreprocessorDefines)
00213   {
00214     nuxAssertMsg(ShaderCode, "[IOpenGLVertexShader::SetShaderCode] Invalid shader code.");
00215     NUX_RETURN_IF_NULL(ShaderCode);
00216     NString ProcessedShaderSource;
00217     NString Defines(VtxShaderPreprocessorDefines);
00218     InsertPreProcessorDefinitions(ShaderCode, ProcessedShaderSource, Defines);
00219 
00220     m_CompiledAndReady = false;
00221     _ShaderCode = ProcessedShaderSource;
00222   }
00223 
00224   bool IOpenGLVertexShader::Compile()
00225   {
00226     size_t CodeSize = _ShaderCode.Size();
00227 
00228     if (CodeSize == 0)
00229     {
00230       nuxDebugMsg("[IOpenGLVertexShader::Compile] Vertex shader source code is empty.");
00231     }
00232 
00233     char *ShaderSource = new char[CodeSize+1];
00234     Memset(ShaderSource, 0, CodeSize + 1);
00235     Memcpy(ShaderSource, _ShaderCode.GetTCharPtr(), CodeSize);
00236 
00237     CHECKGL(glShaderSource(_OpenGLID, 1, (const GLcharARB **) &ShaderSource, NULL));
00238     delete [] ShaderSource;
00239 
00240     // compile vertex shader object
00241     CHECKGL(glCompileShader(_OpenGLID));
00242 
00243     // check if shader compiled
00244     m_CompiledAndReady = false;
00245     CHECKGL(glGetShaderiv(_OpenGLID, GL_COMPILE_STATUS, &m_CompiledAndReady));
00246 
00247     if (!m_CompiledAndReady)
00248     {
00249       ANSICHAR *InfoLogBuffer = 0;
00250       GLint InfoLogBufferSize = 0;
00251       GLint InfoLogReturnSize = 0;
00252       GLint iLog = 0;
00253 
00254       glGetShaderiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog);
00255       InfoLogBuffer = new ANSICHAR[iLog+1];
00256       InfoLogBufferSize = iLog + 1;
00257       glGetShaderInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer);
00258 
00259       if (InfoLogReturnSize != 0)
00260       {
00261         nuxError("[IOpenGLVertexShader::Compile] glCompileShader: %s", InfoLogBuffer);
00262       }
00263 
00264       delete[] InfoLogBuffer;
00265     }
00266 
00267     return(m_CompiledAndReady ? true : false);
00268   }
00269 
00270   bool IOpenGLVertexShader::IsValid()
00271   {
00272     return(m_CompiledAndReady ? true : false);
00273   }
00274 
00275   IOpenGLPixelShader::IOpenGLPixelShader(NString ShaderName)
00276     :   IOpenGLShader(ShaderName, RT_GLSL_PIXELSHADER)
00277     ,   m_CompiledAndReady(false)
00278 
00279   {
00280     _OpenGLID = glCreateShader(GL_FRAGMENT_SHADER_ARB);
00281     CHECKGL_MSG( glCreateShader(GL_FRAGMENT_SHADER_ARB));
00282   }
00283 
00284   IOpenGLPixelShader::~IOpenGLPixelShader()
00285   {
00286     CHECKGL(glDeleteShader(_OpenGLID));
00287     _OpenGLID = 0;
00288     m_CompiledAndReady = false;
00289   }
00290 
00291   void IOpenGLPixelShader::SetShaderCode(const char *ShaderCode, const char *FrgShaderPreprocessorDefines)
00292   {
00293     nuxAssertMsg(ShaderCode, "[IOpenGLPixelShader::SetShaderCode] Invalid shader code.");
00294     NUX_RETURN_IF_NULL(ShaderCode);
00295     NString ProcessedShaderSource;
00296     NString Defines(FrgShaderPreprocessorDefines);
00297     InsertPreProcessorDefinitions(ShaderCode, ProcessedShaderSource, Defines);
00298 
00299     m_CompiledAndReady = false;
00300     _ShaderCode = ProcessedShaderSource;
00301   }
00302 
00303   bool IOpenGLPixelShader::Compile()
00304   {
00305 
00306     GLint CodeSize = (GLint) _ShaderCode.Size();
00307 
00308     if (CodeSize == 0)
00309     {
00310       nuxDebugMsg("[IOpenGLPixelShader::Compile] Pixel shader source code is empty.");
00311     }
00312 
00313     char *ShaderSource = new char[CodeSize+1];
00314     Memset(ShaderSource, 0, CodeSize + 1);
00315     Memcpy(ShaderSource, _ShaderCode.m_string.c_str(), CodeSize);
00316     CHECKGL(glShaderSource(_OpenGLID, 1, (const GLcharARB **) &ShaderSource, &CodeSize));
00317     delete [] ShaderSource;
00318 
00319     // compile pixel shader object
00320     CHECKGL(glCompileShader(_OpenGLID));
00321 
00322     // check if shader compiled
00323     m_CompiledAndReady = false;
00324     CHECKGL(glGetShaderiv(_OpenGLID, GL_COMPILE_STATUS, &m_CompiledAndReady));
00325 
00326     if (!m_CompiledAndReady)
00327     {
00328       ANSICHAR *InfoLogBuffer = 0;
00329       GLint InfoLogBufferSize = 0;
00330       GLint InfoLogReturnSize = 0;
00331       GLint iLog = 0;
00332 
00333       glGetShaderiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog);
00334       InfoLogBuffer = new ANSICHAR[iLog+1];
00335       InfoLogBufferSize = iLog + 1;
00336       glGetShaderInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer);
00337 
00338       if (InfoLogReturnSize != 0)
00339       {
00340         nuxError("[IOpenGLPixelShader::Compile] glCompileShader: %s", InfoLogBuffer);
00341       }
00342       
00343       printf("Error: %s \n COMPILE \n", InfoLogBuffer);
00344 
00345       delete[] InfoLogBuffer;
00346     }
00347 
00348     return(m_CompiledAndReady ? true : false);
00349   }
00350 
00351   bool IOpenGLPixelShader::IsValid()
00352   {
00353     return(m_CompiledAndReady ? true : false);
00354   }
00355 
00356 #if 0
00357   IOpenGLGeometryShader::IOpenGLGeometryShader(NString ShaderName)
00358     :   IOpenGLShader(ShaderName, RT_GLSL_GEOMETRYSHADER)
00359     ,   m_CompiledAndReady(false)
00360 
00361   {
00362     _OpenGLID = glCreateShader(GL_GEOMETRY_SHADER);
00363     CHECKGL_MSG(glCreateShader(GL_GEOMETRY_SHADER));
00364   }
00365 
00366   IOpenGLGeometryShader::~IOpenGLGeometryShader()
00367   {
00368     CHECKGL(glDeleteShader(_OpenGLID));
00369     _OpenGLID = 0;
00370     m_CompiledAndReady = false;
00371   }
00372 
00373   void IOpenGLGeometryShader::SetShaderCode(const char *ShaderCode, const char *GeometryShaderPreprocessorDefines)
00374   {
00375     nuxAssertMsg(ShaderCode, "[IOpenGLGeometryShader::SetShaderCode] Invalid shader code.");
00376     NUX_RETURN_IF_NULL(ShaderCode);
00377     NString ProcessedShaderSource;
00378     NString Defines(GeometryShaderPreprocessorDefines);
00379     InsertPreProcessorDefinitions(ShaderCode, ProcessedShaderSource, Defines);
00380 
00381     m_CompiledAndReady = false;
00382     _ShaderCode = ProcessedShaderSource;
00383   }
00384 
00385   bool IOpenGLGeometryShader::Compile()
00386   {
00387 
00388     GLint CodeSize = (GLint) _ShaderCode.Size();
00389 
00390     if (CodeSize == 0)
00391     {
00392       nuxDebugMsg("[IOpenGLGeometryShader::Compile] Pixel shader source code is empty.");
00393     }
00394 
00395     char *ShaderSource = new char[CodeSize+1];
00396     Memset(ShaderSource, 0, CodeSize + 1);
00397     Memcpy(ShaderSource, _ShaderCode.m_string.c_str(), CodeSize);
00398     CHECKGL(glShaderSource(_OpenGLID, 1, (const GLcharARB **) &ShaderSource, &CodeSize));
00399     delete [] ShaderSource;
00400 
00401     // compile pixel shader object
00402     CHECKGL(glCompileShader(_OpenGLID));
00403 
00404     // check if shader compiled
00405     m_CompiledAndReady = false;
00406     CHECKGL(glGetShaderiv(_OpenGLID, GL_COMPILE_STATUS, &m_CompiledAndReady));
00407 
00408     if (!m_CompiledAndReady)
00409     {
00410       ANSICHAR *InfoLogBuffer = 0;
00411       GLint InfoLogBufferSize = 0;
00412       GLint InfoLogReturnSize = 0;
00413       GLint iLog = 0;
00414 
00415       glGetShaderiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog);
00416       InfoLogBuffer = new ANSICHAR[iLog+1];
00417       InfoLogBufferSize = iLog + 1;
00418       glGetShaderInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer);
00419 
00420       if (InfoLogReturnSize != 0)
00421       {
00422         nuxError("[IOpenGLGeometryShader::Compile] glCompileShader: %s", InfoLogBuffer);
00423       }
00424 
00425       delete InfoLogBuffer;
00426     }
00427 
00428     return(m_CompiledAndReady ? true : false);
00429   }
00430 
00431   bool IOpenGLGeometryShader::IsValid()
00432   {
00433     return(m_CompiledAndReady ? true : false);
00434   }
00435 
00436   void IOpenGLGeometryShader::SetInputPrimitiveType(GLenum type)
00437   {
00438     CHECKGL(glProgramParameteri(_OpenGLID, GL_GEOMETRY_INPUT_TYPE_EXT, type));
00439   }
00440 
00441   void IOpenGLGeometryShader::SetOutputPrimitiveType(GLenum type)
00442   {
00443     CHECKGL(glProgramParameteri(_OpenGLID, GL_GEOMETRY_OUTPUT_TYPE_EXT, type));
00444   }
00445 
00446   void IOpenGLGeometryShader::SetMaxVertexOutput(int max_vertex_output)
00447   {
00448     CHECKGL(glProgramParameteri(_OpenGLID, GL_GEOMETRY_VERTICES_OUT_EXT, max_vertex_output));
00449   }
00450 #endif
00451 
00452   IOpenGLShaderProgram::IOpenGLShaderProgram(NString ShaderProgramName)
00453     :   IOpenGLResource(RT_GLSL_SHADERPROGRAM)
00454     ,   _FirstParameter(0)
00455     ,   m_CompiledAndReady(false)
00456     ,   _ShaderProgramName(ShaderProgramName)
00457   {
00458     _OpenGLID = glCreateProgram();
00459     CHECKGL_MSG( glCreateProgram());
00460   }
00461 
00462   IOpenGLShaderProgram::~IOpenGLShaderProgram()
00463   {
00464     if (local::last_loaded_shader == _OpenGLID)
00465     {
00466       CHECKGL(glUseProgramObjectARB(0));
00467       local::last_loaded_shader = 0;
00468     }
00469       
00470     CHECKGL(glDeleteProgram(_OpenGLID));
00471     _OpenGLID = 0;
00472     m_CompiledAndReady = false;
00473   }
00474 
00475   void IOpenGLShaderProgram::LoadIShaderFile(const char *ShaderFileName, const char *VtxShaderPreprocessorDefines, const char *FrgShaderPreprocessorDefines)
00476   {
00477     nuxAssertMsg(ShaderFileName, "[IOpenGLShaderProgram::LoadIShaderFile] Invalid shader file name.");
00478     NUX_RETURN_IF_NULL(ShaderFileName);
00479     NString SourceCode;
00480     LoadFileToString(SourceCode, ShaderFileName);
00481     LoadIShader(&SourceCode[0], VtxShaderPreprocessorDefines, FrgShaderPreprocessorDefines);
00482   }
00483 
00484   void IOpenGLShaderProgram::LoadIShader(const char *ShaderCode, const char *VtxShaderPreprocessorDefines, const char *FrgShaderPreprocessorDefines)
00485   {
00486     nuxAssertMsg(ShaderCode, "[IOpenGLShaderProgram::LoadIShader] Invalid shader code.");
00487     NUX_RETURN_IF_NULL(ShaderCode);
00488     NString VertexShaderSource;
00489     ExtractShaderString3("[Vertex Shader]", ShaderCode, VertexShaderSource, NString(VtxShaderPreprocessorDefines));
00490     NString PixelShaderSource;
00491     ExtractShaderString3("[Fragment Shader]", ShaderCode, PixelShaderSource, NString(FrgShaderPreprocessorDefines));
00492 
00493     ObjectPtr<IOpenGLVertexShader> vs = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexShader(); //new IOpenGLVertexShader;
00494     ObjectPtr<IOpenGLPixelShader> ps = GetGraphicsDisplay()->GetGpuDevice()->CreatePixelShader(); //new IOpenGLPixelShader;
00495 
00496     vs->SetShaderCode(&VertexShaderSource[0]);
00497     ps->SetShaderCode(&PixelShaderSource[0]);
00498     vs->Compile();
00499     ps->Compile();
00500 
00501     ShaderObjectList.clear();
00502 
00503     AddShaderObject(vs);
00504     AddShaderObject(ps);
00505   }
00506 
00507   void IOpenGLShaderProgram::LoadVertexShader(const char *glslshader, const char *VtxShaderPreprocessorDefines)
00508   {
00509     nuxAssertMsg(glslshader, "[IOpenGLShaderProgram::LoadVertexShader] Invalid shader code.");
00510     NUX_RETURN_IF_NULL(glslshader);
00511     ObjectPtr<IOpenGLVertexShader> vs = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexShader(); //new IOpenGLVertexShader;
00512 
00513     NString ProcessedShaderSource;
00514     NString Defines(VtxShaderPreprocessorDefines);
00515     InsertPreProcessorDefinitions(glslshader, ProcessedShaderSource, Defines);
00516 
00517     vs->SetShaderCode(glslshader);
00518     vs->Compile();
00519     AddShaderObject(vs);
00520   }
00521 
00522   void IOpenGLShaderProgram::LoadPixelShader(const char *glslshader, const char *FrgShaderPreprocessorDefines)
00523   {
00524     nuxAssertMsg(glslshader, "[IOpenGLShaderProgram::LoadPixelShader] Invalid shader code.");
00525     NUX_RETURN_IF_NULL(glslshader);
00526     ObjectPtr<IOpenGLPixelShader> ps = GetGraphicsDisplay()->GetGpuDevice()->CreatePixelShader(); //new IOpenGLPixelShader;
00527 
00528     NString ProcessedShaderSource;
00529     NString Defines(FrgShaderPreprocessorDefines);
00530     InsertPreProcessorDefinitions(glslshader, ProcessedShaderSource, Defines);
00531 
00532     ps->SetShaderCode(glslshader);
00533     ps->Compile();
00534     AddShaderObject(ps);
00535   }
00536 
00537   void IOpenGLShaderProgram::AddShaderObject(ObjectPtr<IOpenGLShader> ShaderObject)
00538   {
00539     ShaderObjectList.push_back(ShaderObject);
00540   }
00541 
00542   void IOpenGLShaderProgram::AddShaderParameter(GLShaderParameter* parameter)
00543   {
00544     GLShaderParameter* temp = _FirstParameter;
00545 
00546     while (temp)
00547     {
00548       if (temp == parameter)
00549       {
00550         // Parameter already added
00551         return;
00552       }
00553       temp = temp->m_NextParameter;
00554     }
00555 
00556     parameter->m_NextParameter = _FirstParameter;
00557     _FirstParameter = parameter;
00558 
00559     // If we add shader parameters after the program is linked, we need to call CheckUniformLocation().
00560     CheckUniformLocation();
00561   }
00562 
00563   void IOpenGLShaderProgram::RemoveShaderObject(ObjectPtr<IOpenGLShader> ShaderObject)
00564   {
00565     std::vector< ObjectPtr<IOpenGLShader> >::iterator it = find(ShaderObjectList.begin(), ShaderObjectList.end(), ShaderObject);
00566 
00567     if (it != ShaderObjectList.end())
00568     {
00569       ShaderObjectList.erase(it);
00570     }
00571   }
00572 
00573   void IOpenGLShaderProgram::ClearShaderObjects()
00574   {
00575     ShaderObjectList.clear();
00576   }
00577 
00578   bool IOpenGLShaderProgram::Link()
00579   {
00580     // Get the number of attached shaders.
00581     GLint NumAttachedShaders;
00582     CHECKGL(glGetProgramiv(_OpenGLID, GL_ATTACHED_SHADERS, &NumAttachedShaders));
00583     GLuint *ShaderObjects = 0;
00584 
00585     if (NumAttachedShaders)
00586     {
00587       ShaderObjects = new GLuint[NumAttachedShaders];
00588     }
00589 
00590     CHECKGL(glGetAttachedShaders(_OpenGLID, NumAttachedShaders, NULL, ShaderObjects));
00591 
00592     // Detach everything first
00593     for (int i = 0; i < (int) NumAttachedShaders; i++)
00594     {
00595       unsigned int obj = ShaderObjects[i];
00596       CHECKGL(glDetachShader(_OpenGLID, obj));
00597     }
00598 
00599     if (NumAttachedShaders)
00600     {
00601       delete[] ShaderObjects;
00602     }
00603 
00604     for (int i = 0; i < (int) ShaderObjectList.size(); i++)
00605     {
00606       if (!ShaderObjectList[i]->IsValid())
00607       {
00608         if (ShaderObjectList[i]->Compile() == false)
00609         {
00610           nuxDebugMsg("[IOpenGLShaderProgram::Link] Attached shader %s does not compile with program: %s.", ShaderObjectList[i]->_ShaderName.GetTCharPtr(), _ShaderProgramName.GetTCharPtr());
00611         }
00612       }
00613 
00614       unsigned int obj = ShaderObjectList[i]->GetOpenGLID();
00615       CHECKGL(glAttachShader(_OpenGLID, obj));
00616     }
00617 
00618     GLint linked;
00619     CHECKGL(glLinkProgram(_OpenGLID));
00620     CHECKGL(glGetProgramiv(_OpenGLID, GL_LINK_STATUS, &linked));
00621 
00622     if (linked == GL_FALSE)
00623     {
00624       ANSICHAR *InfoLogBuffer = 0;
00625       GLint InfoLogBufferSize = 0;
00626       GLint InfoLogReturnSize = 0;
00627       GLint iLog = 0;
00628       glGetProgramiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog);
00629       InfoLogBuffer = new ANSICHAR[iLog+1];
00630       InfoLogBufferSize = iLog + 1;
00631 
00632       glGetProgramInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer);
00633 
00634       if (InfoLogReturnSize != 0)
00635       {
00636         nuxError("[IOpenGLShaderProgram::Link] glLinkProgram: %s", InfoLogBuffer);
00637       }
00638 
00639       delete[] InfoLogBuffer;
00640       m_CompiledAndReady = false;
00641       return m_CompiledAndReady;
00642     }
00643 
00644     GLint validated;
00645     // glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state.
00646     CHECKGL(glValidateProgram(_OpenGLID));
00647     CHECKGL(glGetProgramiv(_OpenGLID, GL_VALIDATE_STATUS, &validated));
00648 
00649     if (validated == GL_FALSE)
00650     {
00651       ANSICHAR *InfoLogBuffer = 0;
00652       GLint InfoLogBufferSize = 0;
00653       GLint InfoLogReturnSize = 0;
00654       GLint iLog = 0;
00655       glGetProgramiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog);
00656       InfoLogBuffer = new ANSICHAR[iLog+1];
00657       InfoLogBufferSize = iLog + 1;
00658 
00659       glGetProgramInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer);
00660 
00661       if (InfoLogReturnSize != 0)
00662       {
00663         nuxError("[IOpenGLShaderProgram::Link] glValidateProgram: %s", InfoLogBuffer);
00664       }
00665 
00666       delete [] InfoLogBuffer;
00667     }
00668 
00669     m_CompiledAndReady = true;
00670 
00671     Begin();
00672     CheckUniformLocation();
00673     CheckAttributeLocation();
00674     
00675     End();
00676 
00677     return m_CompiledAndReady;
00678   }
00679 
00680   void IOpenGLShaderProgram::SetShaderTracking(bool enabled)
00681   {
00682     local::enable_tracking = enabled;
00683     local::last_loaded_shader = 0;
00684     CHECKGL(glUseProgramObjectARB(0));
00685   }
00686 
00687   void IOpenGLShaderProgram::Begin(void)
00688   {
00689     if (local::last_loaded_shader == _OpenGLID && local::enable_tracking)
00690       return;
00691     
00692     local::last_loaded_shader = _OpenGLID;
00693     CHECKGL(glUseProgramObjectARB(_OpenGLID));
00694   }
00695 
00696   void IOpenGLShaderProgram::End(void)
00697   {
00698     if (!local::enable_tracking)
00699       CHECKGL(glUseProgramObjectARB(0));
00700   }
00701 
00702   void IOpenGLShaderProgram::CheckAttributeLocation()
00703   {
00704     //ResetAttributeVariable(m_ProgramAttributeDefinition);
00705     for (int i = 0; i < NUM_VERTEX_SHADER_INPUT_ATTRIBUTE; i++)
00706     {
00707       m_ProgramAttributeDefinition[i].attribute_index = -1;
00708       m_ProgramAttributeDefinition[i].attribute_name = "";
00709       m_ProgramAttributeDefinition[i].type = VAT_UNDEFINED;
00710       m_ProgramAttributeDefinition[i].valid = false;
00711     }
00712 
00713     char active_attribute_name[256];
00714     GLsizei length;
00715     GLint size;
00716     GLenum type;
00717 
00718     GLint num_active_attributes;
00719     CHECKGL(glGetObjectParameterivARB(_OpenGLID, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &num_active_attributes));
00720 
00721 
00722     //         Vertex Attribute Aliasing
00723     //         GLSL attempts to eliminate aliasing of vertex attributes but this is integral to NVIDIA's hardware
00724     //         approach and necessary for maintaining compatibility with existing OpenGL applications that NVIDIA customers rely on.
00725     //         NVIDIA's GLSL implementation therefore does not allow built-in vertex attributes to collide with a
00726     //         generic vertex attributes that is assigned to a particular vertex attribute index with glBindAttribLocation.
00727     //         For example, you should not use gl_Normal(a built-in vertex attribute) and also use glBindAttribLocation to
00728     //         bind a generic vertex attribute named "whatever" to vertex attribute index 2 because gl_Normal aliases to index 2.
00729     //
00730     //         Built-in vertex attribute name      Incompatible aliased vertex attribute index
00731     //         gl_Vertex                           0
00732     //         gl_Normal                           2
00733     //         gl_Color                            3
00734     //         gl_SecondaryColor                   4
00735     //         gl_FogCoord                         5
00736     //         gl_MultiTexCoord0                   8
00737     //         gl_MultiTexCoord1                   9
00738     //         gl_MultiTexCoord2                   10
00739     //         gl_MultiTexCoord3                   11
00740     //         gl_MultiTexCoord4                   12
00741     //         gl_MultiTexCoord5                   13
00742     //         gl_MultiTexCoord6                   14
00743     //         gl_MultiTexCoord7                   15
00744     //         The compiler will automatically assign vertex shader attribute variables not pre-assigned
00745     //         by glBindAttribLocation to locations that do not collide with any built-in attribute variables
00746     //         used by the vertex shader. The assigned locations can be queries with glGetAttribLocation.
00747     //         This means that a developer only needs to worry about collisions when they are explicitly requesting
00748     //         an attribute to be bound to a specific location.
00749 
00750     for (int index = 0; index < num_active_attributes; index++)
00751     {
00752       glGetActiveAttribARB(_OpenGLID,
00753                             index,
00754                             256,
00755                             &length,
00756                             &size,
00757                             &type,
00758                             active_attribute_name);
00759       CHECKGL_MSG( glGetActiveAttribARB );
00760       m_ProgramAttributeDefinition[index].attribute_index = glGetAttribLocationARB(_OpenGLID, active_attribute_name);
00761       CHECKGL_MSG( glGetAttribLocationARB );
00762       m_ProgramAttributeDefinition[index].attribute_name = active_attribute_name;
00763       m_ProgramAttributeDefinition[index].valid = true;
00764 
00765       switch(type)
00766       {
00767         case GL_FLOAT:
00768           m_ProgramAttributeDefinition[index].type = VAT_FLOAT;
00769           break;
00770         case GL_FLOAT_VEC2:
00771           m_ProgramAttributeDefinition[index].type = VAT_FLOAT2;
00772           break;
00773         case GL_FLOAT_VEC3:
00774           m_ProgramAttributeDefinition[index].type = VAT_FLOAT3;
00775           break;
00776         case GL_FLOAT_VEC4:
00777           m_ProgramAttributeDefinition[index].type = VAT_FLOAT4;
00778           break;
00779 
00780         case GL_FLOAT_MAT2:
00781         case GL_FLOAT_MAT3:
00782         case GL_FLOAT_MAT4:
00783         default:
00784           //todo
00785           nuxAssert(0);
00786       }
00787     }
00788   }
00789 
00790   void IOpenGLShaderProgram::CheckUniformLocation()
00791   {
00792     GLShaderParameter *parameter = _FirstParameter;
00793 
00794     while (m_CompiledAndReady && parameter)
00795     {
00796       int location = glGetUniformLocationARB(_OpenGLID, TCHAR_TO_ANSI(parameter->m_Name.GetTCharPtr()));
00797       CHECKGL_MSG( glGetUniformLocationARB(_OpenGLID, TCHAR_TO_ANSI(parameter->m_Name.GetTCharPtr())));
00798 
00799       //nuxDebugMsg("[IOpenGLShaderProgram::CheckUniformLocation] Location index: %d", location);
00800       if (location == -1 && (!parameter->m_bIsOptional))
00801       {
00802         nuxDebugMsg("[IOpenGLShaderProgram::CheckUniformLocation] Couldn't find shader program parameter %s \n", parameter->m_Name.GetTCharPtr());
00803         nuxAssert(0);
00804       }
00805 
00806       GLint size = 0;
00807       GLenum type = 0;
00808 
00809       if (location >= 0)
00810       {
00811         CHECKGL(glGetActiveUniformARB(_OpenGLID, location, 0, NULL /*&length*/, &size, &type, NULL));
00812       }
00813 
00814       parameter->m_Index = location;
00815       parameter->m_Size = size;
00816       parameter->m_Type = type;
00817 
00818       parameter = parameter->m_NextParameter;
00819     }
00820   }
00821 
00822   int IOpenGLShaderProgram::GetAttributeLocation(const char *AttributeName)
00823   {
00824     for (int i = 0; i < 16 /*NUM_VERTEX_SHADER_INPUT_ATTRIBUTE*/; i++)
00825     {
00826       if (m_ProgramAttributeDefinition[i].attribute_name == AttributeName)
00827         return m_ProgramAttributeDefinition[i].attribute_index;
00828     }
00829 
00830     return -1;
00831   }
00832 
00833   bool IOpenGLShaderProgram::SetUniform1f(char *varname, GLfloat v0)
00834   {
00835     GLint loc = GetUniformLocationARB(varname);
00836 
00837     if (loc == -1) return false; // can't find variable
00838 
00839     glUniform1fARB(loc, v0);
00840 
00841     return true;
00842   }
00843   bool IOpenGLShaderProgram::SetUniform1f(GLint loc, GLfloat v0)
00844   {
00845     if (loc == -1) return false; // can't find variable
00846 
00847     glUniform1fARB(loc, v0);
00848     return true;
00849   }
00850 
00851 
00852   bool IOpenGLShaderProgram::SetUniform2f(char *varname, GLfloat v0, GLfloat v1)
00853   {
00854     GLint loc = GetUniformLocationARB(varname);
00855 
00856     if (loc == -1) return false; // can't find variable
00857 
00858     glUniform2fARB(loc, v0, v1);
00859 
00860     return true;
00861   }
00862   bool IOpenGLShaderProgram::SetUniform2f(GLint loc, GLfloat v0, GLfloat v1)
00863   {
00864     if (loc == -1) return false; // can't find variable
00865 
00866     glUniform2fARB(loc, v0, v1);
00867     return true;
00868   }
00869 
00870   bool IOpenGLShaderProgram::SetUniform3f(char *varname, GLfloat v0, GLfloat v1, GLfloat v2)
00871   {
00872     GLint loc = GetUniformLocationARB(varname);
00873 
00874     if (loc == -1) return false; // can't find variable
00875 
00876     glUniform3fARB(loc, v0, v1, v2);
00877 
00878     return true;
00879   }
00880   bool IOpenGLShaderProgram::SetUniform3f(GLint loc, GLfloat v0, GLfloat v1, GLfloat v2)
00881   {
00882     if (loc == -1) return false; // can't find variable
00883 
00884     glUniform3fARB(loc, v0, v1, v2);
00885 
00886     return true;
00887   }
00888 
00889   bool IOpenGLShaderProgram::SetUniform4f(char *varname, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
00890   {
00891     GLint loc = GetUniformLocationARB(varname);
00892 
00893     if (loc == -1) return false; // can't find variable
00894 
00895     glUniform4fARB(loc, v0, v1, v2, v3);
00896 
00897     return true;
00898   }
00899   bool IOpenGLShaderProgram::SetUniform4f(GLint loc, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3)
00900   {
00901     if (loc == -1) return false; // can't find variable
00902 
00903     glUniform4fARB(loc, v0, v1, v2, v3);
00904 
00905     return true;
00906   }
00907 
00908   bool IOpenGLShaderProgram::SetUniform1i(char *varname, GLint v0)
00909   {
00910     GLint loc = GetUniformLocationARB(varname);
00911 
00912     if (loc == -1) return false; // can't find variable
00913 
00914     glUniform1iARB(loc, v0);
00915 
00916     return true;
00917   }
00918   bool IOpenGLShaderProgram::SetUniform1i(GLint loc, GLint v0)
00919   {
00920     if (loc == -1) return false; // can't find variable
00921 
00922     glUniform1iARB(loc, v0);
00923 
00924     return true;
00925   }
00926 
00927   bool IOpenGLShaderProgram::SetUniform2i(char *varname, GLint v0, GLint v1)
00928   {
00929     GLint loc = GetUniformLocationARB(varname);
00930 
00931     if (loc == -1) return false; // can't find variable
00932 
00933     glUniform2iARB(loc, v0, v1);
00934 
00935 
00936     return true;
00937   }
00938   bool IOpenGLShaderProgram::SetUniform2i(GLint loc, GLint v0, GLint v1)
00939   {
00940     if (loc == -1) return false; // can't find variable
00941 
00942     glUniform2iARB(loc, v0, v1);
00943 
00944 
00945     return true;
00946   }
00947 
00948   bool IOpenGLShaderProgram::SetUniform3i(char *varname, GLint v0, GLint v1, GLint v2)
00949   {
00950     GLint loc = GetUniformLocationARB(varname);
00951 
00952     if (loc == -1) return false; // can't find variable
00953 
00954     glUniform3iARB(loc, v0, v1, v2);
00955 
00956     return true;
00957   }
00958   bool IOpenGLShaderProgram::SetUniform3i(GLint loc, GLint v0, GLint v1, GLint v2)
00959   {
00960     if (loc == -1) return false; // can't find variable
00961 
00962     glUniform3iARB(loc, v0, v1, v2);
00963 
00964     return true;
00965   }
00966 
00967   bool IOpenGLShaderProgram::SetUniform4i(char *varname, GLint v0, GLint v1, GLint v2, GLint v3)
00968   {
00969     GLint loc = GetUniformLocationARB(varname);
00970 
00971     if (loc == -1) return false; // can't find variable
00972 
00973     glUniform4iARB(loc, v0, v1, v2, v3);
00974 
00975     return true;
00976   }
00977   bool IOpenGLShaderProgram::SetUniform4i(GLint loc, GLint v0, GLint v1, GLint v2, GLint v3)
00978   {
00979     if (loc == -1) return false; // can't find variable
00980 
00981     glUniform4iARB(loc, v0, v1, v2, v3);
00982 
00983     return true;
00984   }
00985 
00986   bool IOpenGLShaderProgram::SetUniform1fv(char *varname, GLsizei count, GLfloat *value)
00987   {
00988     GLint loc = GetUniformLocationARB(varname);
00989 
00990     if (loc == -1) return false; // can't find variable
00991 
00992     glUniform1fvARB(loc, count, value);
00993 
00994     return true;
00995   }
00996   bool IOpenGLShaderProgram::SetUniform1fv(GLint loc, GLsizei count, GLfloat *value)
00997   {
00998     if (loc == -1) return false; // can't find variable
00999 
01000     glUniform1fvARB(loc, count, value);
01001 
01002     return true;
01003   }
01004 
01005   bool IOpenGLShaderProgram::SetUniform2fv(char *varname, GLsizei count, GLfloat *value)
01006   {
01007     GLint loc = GetUniformLocationARB(varname);
01008 
01009     if (loc == -1) return false; // can't find variable
01010 
01011     glUniform2fvARB(loc, count, value);
01012 
01013     return true;
01014   }
01015   bool IOpenGLShaderProgram::SetUniform2fv(GLint loc, GLsizei count, GLfloat *value)
01016   {
01017     if (loc == -1) return false; // can't find variable
01018 
01019     glUniform2fvARB(loc, count, value);
01020 
01021     return true;
01022   }
01023 
01024   bool IOpenGLShaderProgram::SetUniform3fv(char *varname, GLsizei count, GLfloat *value)
01025   {
01026     GLint loc = GetUniformLocationARB(varname);
01027 
01028     if (loc == -1) return false; // can't find variable
01029 
01030     glUniform3fvARB(loc, count, value);
01031 
01032     return true;
01033   }
01034   bool IOpenGLShaderProgram::SetUniform3fv(GLint loc, GLsizei count, GLfloat *value)
01035   {
01036     if (loc == -1) return false; // can't find variable
01037 
01038     glUniform3fvARB(loc, count, value);
01039 
01040     return true;
01041   }
01042 
01043   bool IOpenGLShaderProgram::SetUniform4fv(char *varname, GLsizei count, GLfloat *value)
01044   {
01045     GLint loc = GetUniformLocationARB(varname);
01046 
01047     if (loc == -1) return false; // can't find variable
01048 
01049     glUniform4fvARB(loc, count, value);
01050 
01051     return true;
01052   }
01053   bool IOpenGLShaderProgram::SetUniform4fv(GLint loc, GLsizei count, GLfloat *value)
01054   {
01055     if (loc == -1) return false; // can't find variable
01056 
01057     glUniform4fvARB(loc, count, value);
01058 
01059     return true;
01060   }
01061 
01062   bool IOpenGLShaderProgram::SetUniform1iv(char *varname, GLsizei count, GLint *value)
01063   {
01064     GLint loc = GetUniformLocationARB(varname);
01065 
01066     if (loc == -1) return false; // can't find variable
01067 
01068     glUniform1ivARB(loc, count, value);
01069 
01070     return true;
01071   }
01072   bool IOpenGLShaderProgram::SetUniform1iv(GLint loc, GLsizei count, GLint *value)
01073   {
01074     if (loc == -1) return false; // can't find variable
01075 
01076     glUniform1ivARB(loc, count, value);
01077 
01078     return true;
01079   }
01080 
01081   bool IOpenGLShaderProgram::SetUniform2iv(char *varname, GLsizei count, GLint *value)
01082   {
01083     GLint loc = GetUniformLocationARB(varname);
01084 
01085     if (loc == -1) return false; // can't find variable
01086 
01087     glUniform2ivARB(loc, count, value);
01088 
01089     return true;
01090   }
01091   bool IOpenGLShaderProgram::SetUniform2iv(GLint loc, GLsizei count, GLint *value)
01092   {
01093     if (loc == -1) return false; // can't find variable
01094 
01095     glUniform2ivARB(loc, count, value);
01096 
01097     return true;
01098   }
01099 
01100   bool IOpenGLShaderProgram::SetUniform3iv(char *varname, GLsizei count, GLint *value)
01101   {
01102     GLint loc = GetUniformLocationARB(varname);
01103 
01104     if (loc == -1) return false; // can't find variable
01105 
01106     glUniform3ivARB(loc, count, value);
01107 
01108     return true;
01109   }
01110   bool IOpenGLShaderProgram::SetUniform3iv(GLint loc, GLsizei count, GLint *value)
01111   {
01112     if (loc == -1) return false; // can't find variable
01113 
01114     glUniform3ivARB(loc, count, value);
01115 
01116     return true;
01117   }
01118 
01119   bool IOpenGLShaderProgram::SetUniform4iv(char *varname, GLsizei count, GLint *value)
01120   {
01121     GLint loc = GetUniformLocationARB(varname);
01122 
01123     if (loc == -1) return false; // can't find variable
01124 
01125     glUniform4ivARB(loc, count, value);
01126 
01127     return true;
01128   }
01129   bool IOpenGLShaderProgram::SetUniform4iv(GLint loc, GLsizei count, GLint *value)
01130   {
01131     if (loc == -1) return false; // can't find variable
01132 
01133     glUniform4ivARB(loc, count, value);
01134 
01135     return true;
01136   }
01137 
01138   bool IOpenGLShaderProgram::SetUniformMatrix2fv(char *varname, GLsizei count, GLboolean transpose, GLfloat *value)
01139   {
01140     GLint loc = GetUniformLocationARB(varname);
01141 
01142     if (loc == -1) return false; // can't find variable
01143 
01144     glUniformMatrix2fvARB(loc, count, transpose, value);
01145 
01146     return true;
01147   }
01148   bool IOpenGLShaderProgram::SetUniformLocMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, GLfloat *value)
01149   {
01150     if (loc == -1) return false; // can't find variable
01151 
01152     glUniformMatrix2fvARB(loc, count, transpose, value);
01153 
01154     return true;
01155   }
01156 
01157   bool IOpenGLShaderProgram::SetUniformMatrix3fv(char *varname, GLsizei count, GLboolean transpose, GLfloat *value)
01158   {
01159     GLint loc = GetUniformLocationARB(varname);
01160 
01161     if (loc == -1) return false; // can't find variable
01162 
01163     glUniformMatrix3fvARB(loc, count, transpose, value);
01164 
01165     return true;
01166   }
01167   bool IOpenGLShaderProgram::SetUniformLocMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, GLfloat *value)
01168   {
01169     if (loc == -1) return false; // can't find variable
01170 
01171     glUniformMatrix3fvARB(loc, count, transpose, value);
01172 
01173     return true;
01174   }
01175 
01176   bool IOpenGLShaderProgram::SetUniformMatrix4fv(char *varname, GLsizei count, GLboolean transpose, GLfloat *value)
01177   {
01178     GLint loc = GetUniformLocationARB(varname);
01179 
01180     if (loc == -1) return false; // can't find variable
01181 
01182     glUniformMatrix4fvARB(loc, count, transpose, value);
01183 
01184     return true;
01185   }
01186   bool IOpenGLShaderProgram::SetUniformLocMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, GLfloat *value)
01187   {
01188     if (loc == -1) return false; // can't find variable
01189 
01190     glUniformMatrix4fvARB(loc, count, transpose, value);
01191 
01192     return true;
01193   }
01194 
01195 
01196   void IOpenGLShaderProgram::GetUniformfv(char *name, GLfloat *values)
01197   {
01198     GLint loc;
01199 
01200     loc = glGetUniformLocationARB(_OpenGLID, name);
01201     CHECKGL_MSG( glGetUniformLocationARB );
01202 
01203     if (loc == -1)
01204     {
01205       std::cout << "Error: can't find uniform variable \"" << name << "\"\n";
01206     }
01207 
01208     CHECKGL(glGetUniformfvARB(_OpenGLID, loc, values));
01209   }
01210 
01211 
01212   void IOpenGLShaderProgram::GetUniformiv(char *name, GLint *values)
01213   {
01214     GLint loc;
01215     loc = glGetUniformLocationARB(_OpenGLID, name);
01216     CHECKGL_MSG( glGetUniformLocationARB );
01217 
01218     if (loc == -1)
01219     {
01220       std::cout << "Error: can't find uniform variable \"" << name << "\"\n";
01221     }
01222 
01223     CHECKGL(glGetUniformivARB(_OpenGLID, loc, values));
01224   }
01225 
01226   int IOpenGLShaderProgram::GetUniformLocationARB(const GLcharARB *name)
01227   {
01228     GLint loc;
01229     loc = glGetUniformLocationARB(_OpenGLID, name);
01230     CHECKGL_MSG( glGetUniformLocationARB );
01231     return loc;
01232   }
01233 
01234   void IOpenGLShaderProgram::GetActiveUniformARB(
01235     GLuint index,
01236     GLsizei maxLength,
01237     GLsizei *length,
01238     GLint *size,
01239     GLenum *type,
01240     GLcharARB *name)
01241   {
01242 
01243     glGetActiveUniformARB(_OpenGLID,
01244                            index,
01245                            maxLength,
01246                            length,
01247                            size,
01248                            type,
01249                            name);
01250     CHECKGL_MSG(glGetActiveUniformARB);
01251   }
01252 
01253 
01254   void IOpenGLShaderProgram::GetObjectParameterfvARB(GLenum pname,
01255       GLfloat *params)
01256   {
01257 #ifndef NUX_OPENGLES_20
01258     glGetObjectParameterfvARB(_OpenGLID,
01259                                pname,
01260                                params);
01261     CHECKGL_MSG(glGetObjectParameterfvARB);
01262 #endif
01263   }
01264 
01265   bool IOpenGLShaderProgram::SetSampler(char *name, int texture_unit)
01266   {
01267     GLint loc = GetUniformLocationARB(name);
01268 
01269     if (loc == -1) return false; // can't find variable
01270 
01271     glUniform1iARB(loc, texture_unit);
01272     return true;
01273   }
01274 
01275 }