nux-1.14.0
|
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 t_size lineStart = 0; 00049 t_size lineCount = 1; 00050 bool startTokenFound = false; 00051 t_size shaderStringStart = 0; 00052 t_size shaderStartLine = 1; 00053 00054 00055 //Loop for all characters in the string 00056 if (ShaderToken != TEXT ("") ) 00057 { 00058 t_size 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], TEXT ("["), 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], TEXT ("\r"), 1) == 0) || (TCharStringNCompare (&ShaderSource[i], TEXT ("\n"), 1) == 0) ) 00089 { 00090 lineStart = i + 1; 00091 } 00092 00093 //Count the new lines 00094 if (TCharStringNCompare (&ShaderSource[i], TEXT ("\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 t_size Pos = RetSource.FindFirstOccurence (TEXT ("#version") ); 00112 00113 while (RetSource[Pos] != TEXT ('\n') ) 00114 { 00115 if (RetSource[Pos] == 0) 00116 break; 00117 00118 ++Pos; 00119 } 00120 00121 if (RetSource[Pos] != 0) 00122 ++Pos; 00123 00124 t_size EndOfLinePosition = 0; 00125 t_size LinePosition = 0; 00126 00127 while ( (EndOfLinePosition = RetSource.FindNextOccurence (TEXT ('\n'), EndOfLinePosition) ) < Pos - 1) 00128 { 00129 ++EndOfLinePosition; 00130 ++LinePosition; 00131 } 00132 00133 RetSource.Insert (Pos, NString::Printf (TEXT ("#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 (TEXT ('\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 t_size Pos = RetSource.FindFirstOccurence (TEXT ("#version") ); 00158 00159 if (Pos != tstring::npos) 00160 { 00161 Pos = RetSource.FindNextOccurence (TEXT ('\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 (TEXT ('\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 (TEXT ('\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 TCHAR *ShaderCode, const TCHAR *VtxShaderPreprocessorDefines) 00213 { 00214 nuxAssertMsg (ShaderCode, TEXT ("[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 t_size CodeSize = _ShaderCode.Size(); 00227 00228 if (CodeSize == 0) 00229 { 00230 nuxDebugMsg (TEXT ("[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 (TEXT ("[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 TCHAR *ShaderCode, const TCHAR *FrgShaderPreprocessorDefines) 00292 { 00293 nuxAssertMsg (ShaderCode, TEXT ("[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 (TEXT ("[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 (TEXT ("[IOpenGLPixelShader::Compile] glCompileShader: %s"), InfoLogBuffer); 00341 } 00342 00343 delete[] InfoLogBuffer; 00344 } 00345 00346 return (m_CompiledAndReady ? true : false); 00347 } 00348 00349 bool IOpenGLPixelShader::IsValid() 00350 { 00351 return (m_CompiledAndReady ? true : false); 00352 } 00353 00354 #if 0 00355 IOpenGLGeometryShader::IOpenGLGeometryShader (NString ShaderName) 00356 : IOpenGLShader (ShaderName, RT_GLSL_GEOMETRYSHADER) 00357 , m_CompiledAndReady (false) 00358 00359 { 00360 _OpenGLID = glCreateShader(GL_GEOMETRY_SHADER); 00361 CHECKGL_MSG(glCreateShader(GL_GEOMETRY_SHADER)); 00362 } 00363 00364 IOpenGLGeometryShader::~IOpenGLGeometryShader() 00365 { 00366 CHECKGL(glDeleteShader(_OpenGLID)); 00367 _OpenGLID = 0; 00368 m_CompiledAndReady = false; 00369 } 00370 00371 void IOpenGLGeometryShader::SetShaderCode (const TCHAR *ShaderCode, const TCHAR *GeometryShaderPreprocessorDefines) 00372 { 00373 nuxAssertMsg (ShaderCode, TEXT("[IOpenGLGeometryShader::SetShaderCode] Invalid shader code.") ); 00374 NUX_RETURN_IF_NULL(ShaderCode); 00375 NString ProcessedShaderSource; 00376 NString Defines(GeometryShaderPreprocessorDefines); 00377 InsertPreProcessorDefinitions(ShaderCode, ProcessedShaderSource, Defines); 00378 00379 m_CompiledAndReady = false; 00380 _ShaderCode = ProcessedShaderSource; 00381 } 00382 00383 bool IOpenGLGeometryShader::Compile() 00384 { 00385 00386 GLint CodeSize = (GLint) _ShaderCode.Size(); 00387 00388 if (CodeSize == 0) 00389 { 00390 nuxDebugMsg(TEXT("[IOpenGLGeometryShader::Compile] Pixel shader source code is empty.") ); 00391 } 00392 00393 char *ShaderSource = new char[CodeSize+1]; 00394 Memset(ShaderSource, 0, CodeSize + 1); 00395 Memcpy(ShaderSource, _ShaderCode.m_string.c_str(), CodeSize); 00396 CHECKGL( glShaderSource(_OpenGLID, 1, (const GLcharARB **) &ShaderSource, &CodeSize) ); 00397 delete [] ShaderSource; 00398 00399 // compile pixel shader object 00400 CHECKGL(glCompileShader(_OpenGLID) ); 00401 00402 // check if shader compiled 00403 m_CompiledAndReady = false; 00404 CHECKGL( glGetShaderiv(_OpenGLID, GL_COMPILE_STATUS, &m_CompiledAndReady) ); 00405 00406 if (!m_CompiledAndReady) 00407 { 00408 ANSICHAR *InfoLogBuffer = 0; 00409 GLint InfoLogBufferSize = 0; 00410 GLint InfoLogReturnSize = 0; 00411 GLint iLog = 0; 00412 00413 glGetShaderiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog); 00414 InfoLogBuffer = new ANSICHAR[iLog+1]; 00415 InfoLogBufferSize = iLog + 1; 00416 glGetShaderInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer); 00417 00418 if (InfoLogReturnSize != 0) 00419 { 00420 nuxError(TEXT("[IOpenGLGeometryShader::Compile] glCompileShader: %s"), InfoLogBuffer); 00421 } 00422 00423 delete InfoLogBuffer; 00424 } 00425 00426 return (m_CompiledAndReady ? true : false); 00427 } 00428 00429 bool IOpenGLGeometryShader::IsValid() 00430 { 00431 return (m_CompiledAndReady ? true : false); 00432 } 00433 00434 void IOpenGLGeometryShader::SetInputPrimitiveType(GLenum type) 00435 { 00436 CHECKGL(glProgramParameteri(_OpenGLID, GL_GEOMETRY_INPUT_TYPE_EXT, type)); 00437 } 00438 00439 void IOpenGLGeometryShader::SetOutputPrimitiveType(GLenum type) 00440 { 00441 CHECKGL(glProgramParameteri(_OpenGLID, GL_GEOMETRY_OUTPUT_TYPE_EXT, type)); 00442 } 00443 00444 void IOpenGLGeometryShader::SetMaxVertexOutput(int max_vertex_output) 00445 { 00446 CHECKGL(glProgramParameteri(_OpenGLID, GL_GEOMETRY_VERTICES_OUT_EXT, max_vertex_output)); 00447 } 00448 #endif 00449 00450 IOpenGLShaderProgram::IOpenGLShaderProgram(NString ShaderProgramName) 00451 : IOpenGLResource(RT_GLSL_SHADERPROGRAM) 00452 , _FirstParameter(0) 00453 , m_CompiledAndReady(false) 00454 , _ShaderProgramName(ShaderProgramName) 00455 { 00456 _OpenGLID = glCreateProgram(); 00457 CHECKGL_MSG( glCreateProgram() ); 00458 } 00459 00460 IOpenGLShaderProgram::~IOpenGLShaderProgram() 00461 { 00462 if (local::last_loaded_shader == _OpenGLID) 00463 { 00464 CHECKGL( glUseProgramObjectARB(0) ); 00465 local::last_loaded_shader = 0; 00466 } 00467 00468 CHECKGL( glDeleteProgram(_OpenGLID) ); 00469 _OpenGLID = 0; 00470 m_CompiledAndReady = false; 00471 } 00472 00473 void IOpenGLShaderProgram::LoadIShaderFile(const TCHAR *ShaderFileName, const TCHAR *VtxShaderPreprocessorDefines, const TCHAR *FrgShaderPreprocessorDefines) 00474 { 00475 nuxAssertMsg(ShaderFileName, TEXT("[IOpenGLShaderProgram::LoadIShaderFile] Invalid shader file name.") ); 00476 NUX_RETURN_IF_NULL(ShaderFileName); 00477 NString SourceCode; 00478 LoadFileToString(SourceCode, ShaderFileName); 00479 LoadIShader(&SourceCode[0], VtxShaderPreprocessorDefines, FrgShaderPreprocessorDefines); 00480 } 00481 00482 void IOpenGLShaderProgram::LoadIShader(const TCHAR *ShaderCode, const TCHAR *VtxShaderPreprocessorDefines, const TCHAR *FrgShaderPreprocessorDefines) 00483 { 00484 nuxAssertMsg(ShaderCode, TEXT("[IOpenGLShaderProgram::LoadIShader] Invalid shader code.") ); 00485 NUX_RETURN_IF_NULL(ShaderCode); 00486 NString VertexShaderSource; 00487 ExtractShaderString3(TEXT("[Vertex Shader]"), ShaderCode, VertexShaderSource, NString(VtxShaderPreprocessorDefines) ); 00488 NString PixelShaderSource; 00489 ExtractShaderString3(TEXT("[Fragment Shader]"), ShaderCode, PixelShaderSource, NString(FrgShaderPreprocessorDefines) ); 00490 00491 ObjectPtr<IOpenGLVertexShader> vs = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexShader(); //new IOpenGLVertexShader; 00492 ObjectPtr<IOpenGLPixelShader> ps = GetGraphicsDisplay()->GetGpuDevice()->CreatePixelShader(); //new IOpenGLPixelShader; 00493 00494 vs->SetShaderCode(&VertexShaderSource[0]); 00495 ps->SetShaderCode(&PixelShaderSource[0]); 00496 vs->Compile(); 00497 ps->Compile(); 00498 00499 ShaderObjectList.clear(); 00500 00501 AddShaderObject(vs); 00502 AddShaderObject(ps); 00503 } 00504 00505 void IOpenGLShaderProgram::LoadVertexShader(const TCHAR *glslshader, const TCHAR *VtxShaderPreprocessorDefines) 00506 { 00507 nuxAssertMsg(glslshader, TEXT("[IOpenGLShaderProgram::LoadVertexShader] Invalid shader code.") ); 00508 NUX_RETURN_IF_NULL(glslshader); 00509 ObjectPtr<IOpenGLVertexShader> vs = GetGraphicsDisplay()->GetGpuDevice()->CreateVertexShader(); //new IOpenGLVertexShader; 00510 00511 NString ProcessedShaderSource; 00512 NString Defines(VtxShaderPreprocessorDefines); 00513 InsertPreProcessorDefinitions(glslshader, ProcessedShaderSource, Defines); 00514 00515 vs->SetShaderCode(glslshader); 00516 vs->Compile(); 00517 AddShaderObject(vs); 00518 } 00519 00520 void IOpenGLShaderProgram::LoadPixelShader(const TCHAR *glslshader, const TCHAR *FrgShaderPreprocessorDefines) 00521 { 00522 nuxAssertMsg(glslshader, TEXT("[IOpenGLShaderProgram::LoadPixelShader] Invalid shader code.") ); 00523 NUX_RETURN_IF_NULL(glslshader); 00524 ObjectPtr<IOpenGLPixelShader> ps = GetGraphicsDisplay()->GetGpuDevice()->CreatePixelShader(); //new IOpenGLPixelShader; 00525 00526 NString ProcessedShaderSource; 00527 NString Defines(FrgShaderPreprocessorDefines); 00528 InsertPreProcessorDefinitions(glslshader, ProcessedShaderSource, Defines); 00529 00530 ps->SetShaderCode(glslshader); 00531 ps->Compile(); 00532 AddShaderObject(ps); 00533 } 00534 00535 void IOpenGLShaderProgram::AddShaderObject(ObjectPtr<IOpenGLShader> ShaderObject) 00536 { 00537 ShaderObjectList.push_back(ShaderObject); 00538 } 00539 00540 void IOpenGLShaderProgram::AddShaderParameter(GLShaderParameter* parameter) 00541 { 00542 GLShaderParameter* temp = _FirstParameter; 00543 00544 while(temp) 00545 { 00546 if(temp == parameter) 00547 { 00548 // Parameter already added 00549 return; 00550 } 00551 temp = temp->m_NextParameter; 00552 } 00553 00554 parameter->m_NextParameter = _FirstParameter; 00555 _FirstParameter = parameter; 00556 00557 // If we add shader parameters after the program is linked, we need to call CheckUniformLocation(). 00558 CheckUniformLocation(); 00559 } 00560 00561 void IOpenGLShaderProgram::RemoveShaderObject(ObjectPtr<IOpenGLShader> ShaderObject) 00562 { 00563 std::vector< ObjectPtr<IOpenGLShader> >::iterator it = find(ShaderObjectList.begin(), ShaderObjectList.end(), ShaderObject); 00564 00565 if (it != ShaderObjectList.end() ) 00566 { 00567 ShaderObjectList.erase(it); 00568 } 00569 } 00570 00571 void IOpenGLShaderProgram::ClearShaderObjects() 00572 { 00573 ShaderObjectList.clear(); 00574 } 00575 00576 bool IOpenGLShaderProgram::Link() 00577 { 00578 // Get the number of attached shaders. 00579 GLint NumAttachedShaders; 00580 CHECKGL( glGetProgramiv(_OpenGLID, GL_ATTACHED_SHADERS, &NumAttachedShaders) ); 00581 GLuint *ShaderObjects = 0; 00582 00583 if (NumAttachedShaders) 00584 { 00585 ShaderObjects = new GLuint[NumAttachedShaders]; 00586 } 00587 00588 CHECKGL( glGetAttachedShaders(_OpenGLID, NumAttachedShaders, NULL, ShaderObjects) ); 00589 00590 // Detach everything first 00591 for (int i = 0; i < (int) NumAttachedShaders; i++) 00592 { 00593 unsigned int obj = ShaderObjects[i]; 00594 CHECKGL( glDetachShader(_OpenGLID, obj) ); 00595 } 00596 00597 if (NumAttachedShaders) 00598 { 00599 delete[] ShaderObjects; 00600 } 00601 00602 for (int i = 0; i < (int) ShaderObjectList.size(); i++) 00603 { 00604 if (!ShaderObjectList[i]->IsValid() ) 00605 { 00606 if (ShaderObjectList[i]->Compile() == false) 00607 { 00608 nuxDebugMsg(TEXT("[IOpenGLShaderProgram::Link] Attached shader %s does not compile with program: %s."), ShaderObjectList[i]->_ShaderName.GetTCharPtr(), _ShaderProgramName.GetTCharPtr() ); 00609 } 00610 } 00611 00612 unsigned int obj = ShaderObjectList[i]->GetOpenGLID(); 00613 CHECKGL( glAttachShader(_OpenGLID, obj) ); 00614 } 00615 00616 GLint linked; 00617 CHECKGL( glLinkProgram(_OpenGLID) ); 00618 CHECKGL( glGetProgramiv(_OpenGLID, GL_LINK_STATUS, &linked) ); 00619 00620 if (linked == GL_FALSE) 00621 { 00622 ANSICHAR *InfoLogBuffer = 0; 00623 GLint InfoLogBufferSize = 0; 00624 GLint InfoLogReturnSize = 0; 00625 GLint iLog = 0; 00626 glGetProgramiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog); 00627 InfoLogBuffer = new ANSICHAR[iLog+1]; 00628 InfoLogBufferSize = iLog + 1; 00629 00630 glGetProgramInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer); 00631 00632 if (InfoLogReturnSize != 0) 00633 { 00634 nuxError(TEXT("[IOpenGLShaderProgram::Link] glLinkProgram: %s"), InfoLogBuffer); 00635 } 00636 00637 delete[] InfoLogBuffer; 00638 m_CompiledAndReady = false; 00639 return m_CompiledAndReady; 00640 } 00641 00642 GLint validated; 00643 // glValidateProgram checks to see whether the executables contained in program can execute given the current OpenGL state. 00644 CHECKGL( glValidateProgram(_OpenGLID) ); 00645 CHECKGL( glGetProgramiv(_OpenGLID, GL_VALIDATE_STATUS, &validated) ); 00646 00647 if (validated == GL_FALSE) 00648 { 00649 ANSICHAR *InfoLogBuffer = 0; 00650 GLint InfoLogBufferSize = 0; 00651 GLint InfoLogReturnSize = 0; 00652 GLint iLog = 0; 00653 glGetProgramiv(_OpenGLID, GL_INFO_LOG_LENGTH, &iLog); 00654 InfoLogBuffer = new ANSICHAR[iLog+1]; 00655 InfoLogBufferSize = iLog + 1; 00656 00657 glGetProgramInfoLog(_OpenGLID, InfoLogBufferSize, &InfoLogReturnSize, InfoLogBuffer); 00658 00659 if (InfoLogReturnSize != 0) 00660 { 00661 nuxError(TEXT("[IOpenGLShaderProgram::Link] glValidateProgram: %s"), InfoLogBuffer); 00662 } 00663 00664 delete [] InfoLogBuffer; 00665 } 00666 00667 m_CompiledAndReady = true; 00668 00669 Begin(); 00670 CheckUniformLocation(); 00671 CheckAttributeLocation(); 00672 00673 End(); 00674 00675 return m_CompiledAndReady; 00676 } 00677 00678 void IOpenGLShaderProgram::SetShaderTracking (bool enabled) 00679 { 00680 local::enable_tracking = enabled; 00681 local::last_loaded_shader = 0; 00682 CHECKGL( glUseProgramObjectARB(0) ); 00683 } 00684 00685 void IOpenGLShaderProgram::Begin(void) 00686 { 00687 if (local::last_loaded_shader == _OpenGLID && local::enable_tracking) 00688 return; 00689 00690 local::last_loaded_shader = _OpenGLID; 00691 CHECKGL( glUseProgramObjectARB(_OpenGLID) ); 00692 } 00693 00694 void IOpenGLShaderProgram::End(void) 00695 { 00696 if (!local::enable_tracking) 00697 CHECKGL( glUseProgramObjectARB(0) ); 00698 } 00699 00700 void IOpenGLShaderProgram::CheckAttributeLocation() 00701 { 00702 //ResetAttributeVariable(m_ProgramAttributeDefinition); 00703 for (int i = 0; i < NUM_VERTEX_SHADER_INPUT_ATTRIBUTE; i++) 00704 { 00705 m_ProgramAttributeDefinition[i].attribute_index = -1; 00706 m_ProgramAttributeDefinition[i].attribute_name = ""; 00707 m_ProgramAttributeDefinition[i].type = VAT_UNDEFINED; 00708 m_ProgramAttributeDefinition[i].valid = false; 00709 } 00710 00711 char active_attribute_name[256]; 00712 GLsizei length; 00713 GLint size; 00714 GLenum type; 00715 00716 GLint num_active_attributes; 00717 CHECKGL( glGetObjectParameterivARB(_OpenGLID, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &num_active_attributes) ); 00718 00719 00720 // Vertex Attribute Aliasing 00721 // GLSL attempts to eliminate aliasing of vertex attributes but this is integral to NVIDIA’s hardware 00722 // approach and necessary for maintaining compatibility with existing OpenGL applications that NVIDIA customers rely on. 00723 // NVIDIA’s GLSL implementation therefore does not allow built-in vertex attributes to collide with a 00724 // generic vertex attributes that is assigned to a particular vertex attribute index with glBindAttribLocation. 00725 // For example, you should not use gl_Normal (a built-in vertex attribute) and also use glBindAttribLocation to 00726 // bind a generic vertex attribute named “whatever” to vertex attribute index 2 because gl_Normal aliases to index 2. 00727 // 00728 // Built-in vertex attribute name Incompatible aliased vertex attribute index 00729 // gl_Vertex 0 00730 // gl_Normal 2 00731 // gl_Color 3 00732 // gl_SecondaryColor 4 00733 // gl_FogCoord 5 00734 // gl_MultiTexCoord0 8 00735 // gl_MultiTexCoord1 9 00736 // gl_MultiTexCoord2 10 00737 // gl_MultiTexCoord3 11 00738 // gl_MultiTexCoord4 12 00739 // gl_MultiTexCoord5 13 00740 // gl_MultiTexCoord6 14 00741 // gl_MultiTexCoord7 15 00742 // The compiler will automatically assign vertex shader attribute variables not pre-assigned 00743 // by glBindAttribLocation to locations that do not collide with any built-in attribute variables 00744 // used by the vertex shader. The assigned locations can be queries with glGetAttribLocation. 00745 // This means that a developer only needs to worry about collisions when they are explicitly requesting 00746 // an attribute to be bound to a specific location. 00747 00748 for (int index = 0; index < num_active_attributes; index++) 00749 { 00750 glGetActiveAttribARB (_OpenGLID, 00751 index, 00752 256, 00753 &length, 00754 &size, 00755 &type, 00756 active_attribute_name); 00757 CHECKGL_MSG ( glGetActiveAttribARB ); 00758 m_ProgramAttributeDefinition[index].attribute_index = glGetAttribLocationARB(_OpenGLID, active_attribute_name); 00759 CHECKGL_MSG ( glGetAttribLocationARB ); 00760 m_ProgramAttributeDefinition[index].attribute_name = active_attribute_name; 00761 m_ProgramAttributeDefinition[index].valid = true; 00762 00763 switch (type) 00764 { 00765 case GL_FLOAT: 00766 m_ProgramAttributeDefinition[index].type = VAT_FLOAT; 00767 break; 00768 case GL_FLOAT_VEC2: 00769 m_ProgramAttributeDefinition[index].type = VAT_FLOAT2; 00770 break; 00771 case GL_FLOAT_VEC3: 00772 m_ProgramAttributeDefinition[index].type = VAT_FLOAT3; 00773 break; 00774 case GL_FLOAT_VEC4: 00775 m_ProgramAttributeDefinition[index].type = VAT_FLOAT4; 00776 break; 00777 00778 case GL_FLOAT_MAT2: 00779 case GL_FLOAT_MAT3: 00780 case GL_FLOAT_MAT4: 00781 default: 00782 //todo 00783 nuxAssert(0); 00784 } 00785 } 00786 } 00787 00788 void IOpenGLShaderProgram::CheckUniformLocation() 00789 { 00790 GLShaderParameter *parameter = _FirstParameter; 00791 00792 while (m_CompiledAndReady && parameter) 00793 { 00794 int location = glGetUniformLocationARB (_OpenGLID, TCHAR_TO_ANSI (parameter->m_Name.GetTCharPtr() ) ); 00795 CHECKGL_MSG ( glGetUniformLocationARB (_OpenGLID, TCHAR_TO_ANSI (parameter->m_Name.GetTCharPtr() ) ) ); 00796 00797 //nuxDebugMsg(TEXT("[IOpenGLShaderProgram::CheckUniformLocation] Location index: %d"), location); 00798 if (location == -1 && (!parameter->m_bIsOptional) ) 00799 { 00800 nuxDebugMsg (TEXT ("[IOpenGLShaderProgram::CheckUniformLocation] Couldn't find shader program parameter %s \n"), parameter->m_Name.GetTCharPtr() ); 00801 nuxAssert (0); 00802 } 00803 00804 GLint size = 0; 00805 GLenum type = 0; 00806 00807 if (location >= 0) 00808 { 00809 CHECKGL ( glGetActiveUniformARB (_OpenGLID, location, 0, NULL /*&length*/, &size, &type, NULL) ); 00810 } 00811 00812 parameter->m_Index = location; 00813 parameter->m_Size = size; 00814 parameter->m_Type = type; 00815 00816 parameter = parameter->m_NextParameter; 00817 } 00818 } 00819 00820 int IOpenGLShaderProgram::GetAttributeLocation (const TCHAR *AttributeName) 00821 { 00822 for (int i = 0; i < 16 /*NUM_VERTEX_SHADER_INPUT_ATTRIBUTE*/; i++) 00823 { 00824 if (m_ProgramAttributeDefinition[i].attribute_name == AttributeName) 00825 return m_ProgramAttributeDefinition[i].attribute_index; 00826 } 00827 00828 return -1; 00829 } 00830 00831 bool IOpenGLShaderProgram::SetUniform1f (char *varname, GLfloat v0) 00832 { 00833 GLint loc = GetUniformLocationARB (varname); 00834 00835 if (loc == -1) return false; // can't find variable 00836 00837 glUniform1fARB (loc, v0); 00838 00839 return true; 00840 } 00841 bool IOpenGLShaderProgram::SetUniform1f (GLint loc, GLfloat v0) 00842 { 00843 if (loc == -1) return false; // can't find variable 00844 00845 glUniform1fARB (loc, v0); 00846 return true; 00847 } 00848 00849 00850 bool IOpenGLShaderProgram::SetUniform2f (char *varname, GLfloat v0, GLfloat v1) 00851 { 00852 GLint loc = GetUniformLocationARB (varname); 00853 00854 if (loc == -1) return false; // can't find variable 00855 00856 glUniform2fARB (loc, v0, v1); 00857 00858 return true; 00859 } 00860 bool IOpenGLShaderProgram::SetUniform2f (GLint loc, GLfloat v0, GLfloat v1) 00861 { 00862 if (loc == -1) return false; // can't find variable 00863 00864 glUniform2fARB (loc, v0, v1); 00865 return true; 00866 } 00867 00868 bool IOpenGLShaderProgram::SetUniform3f (char *varname, GLfloat v0, GLfloat v1, GLfloat v2) 00869 { 00870 GLint loc = GetUniformLocationARB (varname); 00871 00872 if (loc == -1) return false; // can't find variable 00873 00874 glUniform3fARB (loc, v0, v1, v2); 00875 00876 return true; 00877 } 00878 bool IOpenGLShaderProgram::SetUniform3f (GLint loc, GLfloat v0, GLfloat v1, GLfloat v2) 00879 { 00880 if (loc == -1) return false; // can't find variable 00881 00882 glUniform3fARB (loc, v0, v1, v2); 00883 00884 return true; 00885 } 00886 00887 bool IOpenGLShaderProgram::SetUniform4f (char *varname, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) 00888 { 00889 GLint loc = GetUniformLocationARB (varname); 00890 00891 if (loc == -1) return false; // can't find variable 00892 00893 glUniform4fARB (loc, v0, v1, v2, v3); 00894 00895 return true; 00896 } 00897 bool IOpenGLShaderProgram::SetUniform4f (GLint loc, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) 00898 { 00899 if (loc == -1) return false; // can't find variable 00900 00901 glUniform4fARB (loc, v0, v1, v2, v3); 00902 00903 return true; 00904 } 00905 00906 bool IOpenGLShaderProgram::SetUniform1i (char *varname, GLint v0) 00907 { 00908 GLint loc = GetUniformLocationARB (varname); 00909 00910 if (loc == -1) return false; // can't find variable 00911 00912 glUniform1iARB (loc, v0); 00913 00914 return true; 00915 } 00916 bool IOpenGLShaderProgram::SetUniform1i (GLint loc, GLint v0) 00917 { 00918 if (loc == -1) return false; // can't find variable 00919 00920 glUniform1iARB (loc, v0); 00921 00922 return true; 00923 } 00924 00925 bool IOpenGLShaderProgram::SetUniform2i (char *varname, GLint v0, GLint v1) 00926 { 00927 GLint loc = GetUniformLocationARB (varname); 00928 00929 if (loc == -1) return false; // can't find variable 00930 00931 glUniform2iARB (loc, v0, v1); 00932 00933 00934 return true; 00935 } 00936 bool IOpenGLShaderProgram::SetUniform2i (GLint loc, GLint v0, GLint v1) 00937 { 00938 if (loc == -1) return false; // can't find variable 00939 00940 glUniform2iARB (loc, v0, v1); 00941 00942 00943 return true; 00944 } 00945 00946 bool IOpenGLShaderProgram::SetUniform3i (char *varname, GLint v0, GLint v1, GLint v2) 00947 { 00948 GLint loc = GetUniformLocationARB (varname); 00949 00950 if (loc == -1) return false; // can't find variable 00951 00952 glUniform3iARB (loc, v0, v1, v2); 00953 00954 return true; 00955 } 00956 bool IOpenGLShaderProgram::SetUniform3i (GLint loc, GLint v0, GLint v1, GLint v2) 00957 { 00958 if (loc == -1) return false; // can't find variable 00959 00960 glUniform3iARB (loc, v0, v1, v2); 00961 00962 return true; 00963 } 00964 00965 bool IOpenGLShaderProgram::SetUniform4i (char *varname, GLint v0, GLint v1, GLint v2, GLint v3) 00966 { 00967 GLint loc = GetUniformLocationARB (varname); 00968 00969 if (loc == -1) return false; // can't find variable 00970 00971 glUniform4iARB (loc, v0, v1, v2, v3); 00972 00973 return true; 00974 } 00975 bool IOpenGLShaderProgram::SetUniform4i (GLint loc, GLint v0, GLint v1, GLint v2, GLint v3) 00976 { 00977 if (loc == -1) return false; // can't find variable 00978 00979 glUniform4iARB (loc, v0, v1, v2, v3); 00980 00981 return true; 00982 } 00983 00984 bool IOpenGLShaderProgram::SetUniform1fv (char *varname, GLsizei count, GLfloat *value) 00985 { 00986 GLint loc = GetUniformLocationARB (varname); 00987 00988 if (loc == -1) return false; // can't find variable 00989 00990 glUniform1fvARB (loc, count, value); 00991 00992 return true; 00993 } 00994 bool IOpenGLShaderProgram::SetUniform1fv (GLint loc, GLsizei count, GLfloat *value) 00995 { 00996 if (loc == -1) return false; // can't find variable 00997 00998 glUniform1fvARB (loc, count, value); 00999 01000 return true; 01001 } 01002 01003 bool IOpenGLShaderProgram::SetUniform2fv (char *varname, GLsizei count, GLfloat *value) 01004 { 01005 GLint loc = GetUniformLocationARB (varname); 01006 01007 if (loc == -1) return false; // can't find variable 01008 01009 glUniform2fvARB (loc, count, value); 01010 01011 return true; 01012 } 01013 bool IOpenGLShaderProgram::SetUniform2fv (GLint loc, GLsizei count, GLfloat *value) 01014 { 01015 if (loc == -1) return false; // can't find variable 01016 01017 glUniform2fvARB (loc, count, value); 01018 01019 return true; 01020 } 01021 01022 bool IOpenGLShaderProgram::SetUniform3fv (char *varname, GLsizei count, GLfloat *value) 01023 { 01024 GLint loc = GetUniformLocationARB (varname); 01025 01026 if (loc == -1) return false; // can't find variable 01027 01028 glUniform3fvARB (loc, count, value); 01029 01030 return true; 01031 } 01032 bool IOpenGLShaderProgram::SetUniform3fv (GLint loc, GLsizei count, GLfloat *value) 01033 { 01034 if (loc == -1) return false; // can't find variable 01035 01036 glUniform3fvARB (loc, count, value); 01037 01038 return true; 01039 } 01040 01041 bool IOpenGLShaderProgram::SetUniform4fv (char *varname, GLsizei count, GLfloat *value) 01042 { 01043 GLint loc = GetUniformLocationARB (varname); 01044 01045 if (loc == -1) return false; // can't find variable 01046 01047 glUniform4fvARB (loc, count, value); 01048 01049 return true; 01050 } 01051 bool IOpenGLShaderProgram::SetUniform4fv (GLint loc, GLsizei count, GLfloat *value) 01052 { 01053 if (loc == -1) return false; // can't find variable 01054 01055 glUniform4fvARB (loc, count, value); 01056 01057 return true; 01058 } 01059 01060 bool IOpenGLShaderProgram::SetUniform1iv (char *varname, GLsizei count, GLint *value) 01061 { 01062 GLint loc = GetUniformLocationARB (varname); 01063 01064 if (loc == -1) return false; // can't find variable 01065 01066 glUniform1ivARB (loc, count, value); 01067 01068 return true; 01069 } 01070 bool IOpenGLShaderProgram::SetUniform1iv (GLint loc, GLsizei count, GLint *value) 01071 { 01072 if (loc == -1) return false; // can't find variable 01073 01074 glUniform1ivARB (loc, count, value); 01075 01076 return true; 01077 } 01078 01079 bool IOpenGLShaderProgram::SetUniform2iv (char *varname, GLsizei count, GLint *value) 01080 { 01081 GLint loc = GetUniformLocationARB (varname); 01082 01083 if (loc == -1) return false; // can't find variable 01084 01085 glUniform2ivARB (loc, count, value); 01086 01087 return true; 01088 } 01089 bool IOpenGLShaderProgram::SetUniform2iv (GLint loc, GLsizei count, GLint *value) 01090 { 01091 if (loc == -1) return false; // can't find variable 01092 01093 glUniform2ivARB (loc, count, value); 01094 01095 return true; 01096 } 01097 01098 bool IOpenGLShaderProgram::SetUniform3iv (char *varname, GLsizei count, GLint *value) 01099 { 01100 GLint loc = GetUniformLocationARB (varname); 01101 01102 if (loc == -1) return false; // can't find variable 01103 01104 glUniform3ivARB (loc, count, value); 01105 01106 return true; 01107 } 01108 bool IOpenGLShaderProgram::SetUniform3iv (GLint loc, GLsizei count, GLint *value) 01109 { 01110 if (loc == -1) return false; // can't find variable 01111 01112 glUniform3ivARB (loc, count, value); 01113 01114 return true; 01115 } 01116 01117 bool IOpenGLShaderProgram::SetUniform4iv (char *varname, GLsizei count, GLint *value) 01118 { 01119 GLint loc = GetUniformLocationARB (varname); 01120 01121 if (loc == -1) return false; // can't find variable 01122 01123 glUniform4ivARB (loc, count, value); 01124 01125 return true; 01126 } 01127 bool IOpenGLShaderProgram::SetUniform4iv (GLint loc, GLsizei count, GLint *value) 01128 { 01129 if (loc == -1) return false; // can't find variable 01130 01131 glUniform4ivARB (loc, count, value); 01132 01133 return true; 01134 } 01135 01136 bool IOpenGLShaderProgram::SetUniformMatrix2fv (char *varname, GLsizei count, GLboolean transpose, GLfloat *value) 01137 { 01138 GLint loc = GetUniformLocationARB (varname); 01139 01140 if (loc == -1) return false; // can't find variable 01141 01142 glUniformMatrix2fvARB (loc, count, transpose, value); 01143 01144 return true; 01145 } 01146 bool IOpenGLShaderProgram::SetUniformLocMatrix2fv (GLint loc, GLsizei count, GLboolean transpose, GLfloat *value) 01147 { 01148 if (loc == -1) return false; // can't find variable 01149 01150 glUniformMatrix2fvARB (loc, count, transpose, value); 01151 01152 return true; 01153 } 01154 01155 bool IOpenGLShaderProgram::SetUniformMatrix3fv (char *varname, GLsizei count, GLboolean transpose, GLfloat *value) 01156 { 01157 GLint loc = GetUniformLocationARB (varname); 01158 01159 if (loc == -1) return false; // can't find variable 01160 01161 glUniformMatrix3fvARB (loc, count, transpose, value); 01162 01163 return true; 01164 } 01165 bool IOpenGLShaderProgram::SetUniformLocMatrix3fv (GLint loc, GLsizei count, GLboolean transpose, GLfloat *value) 01166 { 01167 if (loc == -1) return false; // can't find variable 01168 01169 glUniformMatrix3fvARB (loc, count, transpose, value); 01170 01171 return true; 01172 } 01173 01174 bool IOpenGLShaderProgram::SetUniformMatrix4fv (char *varname, GLsizei count, GLboolean transpose, GLfloat *value) 01175 { 01176 GLint loc = GetUniformLocationARB (varname); 01177 01178 if (loc == -1) return false; // can't find variable 01179 01180 glUniformMatrix4fvARB (loc, count, transpose, value); 01181 01182 return true; 01183 } 01184 bool IOpenGLShaderProgram::SetUniformLocMatrix4fv (GLint loc, GLsizei count, GLboolean transpose, GLfloat *value) 01185 { 01186 if (loc == -1) return false; // can't find variable 01187 01188 glUniformMatrix4fvARB (loc, count, transpose, value); 01189 01190 return true; 01191 } 01192 01193 01194 void IOpenGLShaderProgram::GetUniformfv (char *name, GLfloat *values) 01195 { 01196 GLint loc; 01197 01198 loc = glGetUniformLocationARB (_OpenGLID, name); 01199 CHECKGL_MSG ( glGetUniformLocationARB ); 01200 01201 if (loc == -1) 01202 { 01203 std::cout << "Error: can't find uniform variable \"" << name << "\"\n"; 01204 } 01205 01206 CHECKGL ( glGetUniformfvARB (_OpenGLID, loc, values) ); 01207 } 01208 01209 01210 void IOpenGLShaderProgram::GetUniformiv (char *name, GLint *values) 01211 { 01212 GLint loc; 01213 loc = glGetUniformLocationARB (_OpenGLID, name); 01214 CHECKGL_MSG ( glGetUniformLocationARB ); 01215 01216 if (loc == -1) 01217 { 01218 std::cout << "Error: can't find uniform variable \"" << name << "\"\n"; 01219 } 01220 01221 CHECKGL ( glGetUniformivARB (_OpenGLID, loc, values) ); 01222 } 01223 01224 int IOpenGLShaderProgram::GetUniformLocationARB (const GLcharARB *name) 01225 { 01226 GLint loc; 01227 loc = glGetUniformLocationARB (_OpenGLID, name); 01228 CHECKGL_MSG ( glGetUniformLocationARB ); 01229 return loc; 01230 } 01231 01232 void IOpenGLShaderProgram::GetActiveUniformARB ( 01233 GLuint index, 01234 GLsizei maxLength, 01235 GLsizei *length, 01236 GLint *size, 01237 GLenum *type, 01238 GLcharARB *name) 01239 { 01240 01241 glGetActiveUniformARB (_OpenGLID, 01242 index, 01243 maxLength, 01244 length, 01245 size, 01246 type, 01247 name); 01248 CHECKGL_MSG (glGetActiveUniformARB); 01249 } 01250 01251 01252 void IOpenGLShaderProgram::GetObjectParameterfvARB (GLenum pname, 01253 GLfloat *params) 01254 { 01255 glGetObjectParameterfvARB (_OpenGLID, 01256 pname, 01257 params); 01258 CHECKGL_MSG (glGetObjectParameterfvARB); 01259 } 01260 01261 bool IOpenGLShaderProgram::SetSampler (char *name, int texture_unit) 01262 { 01263 GLint loc = GetUniformLocationARB (name); 01264 01265 if (loc == -1) return false; // can't find variable 01266 01267 glUniform1iARB (loc, texture_unit); 01268 return true; 01269 } 01270 01271 }