gl_glsl_shader.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2008 by Kutumov Alexey                                  *
00003  *   ru.pixel@gmail.com                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 
00033 #include "gl_glsl_shader_system/gl_glsl_shader.h"
00034 #include <GL/glew.h>
00035 
00036 #include "gpucalc/text_file_loader.h"
00037 #include "gpucalc/graphic_core.h"
00038 #include "gpucalc/log_manager.h"
00039 #include "gpucalc/application.h"
00040 #include "gpucalc/string_util.h"
00041 #include "gpucalc/uniform.h"
00042 #include "gpucalc/texture.h"
00043 
00044 namespace gpucalc
00045 {
00046  GLGLSLShader::GLGLSLShader(const std::string & ShaderName, ShaderSystem * system):
00047   Object(_GLGLSLShaderClassName, ShaderName), Shader(_GLGLSLShaderClassName, ShaderName, system),
00048   mGLSLProgramID(0), mGLSLFragmentShaderID(0), mMultiTextureNumber(0), mUniformVector(),
00049   mIsCompiled(false), mIsDebug(false), mShaderSource(), mShaderCompilerParams()
00050  {
00051   mGLSLProgramID = glCreateProgramObjectARB();
00052   LogManager::getSingleton().logMessage(this, "GLSL program created with OpenGL ID: " +
00053    auxillary::StringUtil::toString(mGLSLProgramID), LML_Trivial);
00054 
00055   mGLSLFragmentShaderID = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
00056   LogManager::getSingleton().logMessage(this, "GLSL fragment shader created with OpenGL ID: " +
00057    auxillary::StringUtil::toString(mGLSLFragmentShaderID), LML_Trivial);
00058   
00059   glAttachObjectARB(mGLSLProgramID, mGLSLFragmentShaderID);
00060  }
00061 
00062 
00063  GLGLSLShader::~GLGLSLShader()
00064  {
00065   glDetachShader(mGLSLProgramID, mGLSLFragmentShaderID);
00066   glDeleteShader(mGLSLFragmentShaderID);
00067   glDeleteProgram(mGLSLProgramID);
00068   LogManager::getSingleton().logMessage(this, "deleted.", LML_Trivial);
00069  }
00070 
00071 
00072  void GLGLSLShader::setSource(const std::string & ShaderSource)
00073  {
00074   mShaderSource = ShaderSource;
00075   mIsCompiled = false;
00076  }
00077 
00078 
00079  void GLGLSLShader::addUniform(Uniform * uniform)
00080  {
00081   if (addToContainer(uniform, mUniformVector))
00082   {
00083    uniform->uploadToGPU();
00084   }
00085  }
00086 
00087 
00088  void GLGLSLShader::removeUniform(Uniform * uniform)
00089  {
00090   removeFromContainer(uniform, mUniformVector);
00091  }
00092 
00093 
00094  void GLGLSLShader::setUniformVariable(Uniform * uniform)
00095  {
00096   GLint Location = getUniformLocation(uniform->getObjectName());
00097   if (Location != -1)
00098   {
00099    switch (uniform->getUniformType())
00100    {
00101     case Uniform::UT_INT_1:
00102      glUniform1iv(Location, uniform->getActualLengthGPU(), static_cast<const int *>(uniform->pointer()));
00103      break;
00104 
00105     case Uniform::UT_INT_2:
00106      glUniform2iv(Location, uniform->getActualLengthGPU(), static_cast<const int *>(uniform->pointer()));
00107      break;
00108 
00109     case Uniform::UT_INT_3:
00110      glUniform3iv(Location, uniform->getActualLengthGPU(), static_cast<const int *>(uniform->pointer()));
00111      break;
00112 
00113     case Uniform::UT_INT_4:
00114      glUniform4iv(Location, uniform->getActualLengthGPU(), static_cast<const int *>(uniform->pointer()));
00115     break;
00116 
00117     case Uniform::UT_FLOAT_1:
00118      glUniform1fv(Location, uniform->getActualLengthGPU(), static_cast<const float *>(uniform->pointer()));
00119      break;
00120 
00121 
00122     case Uniform::UT_FLOAT_2:
00123      glUniform2fv(Location, uniform->getActualLengthGPU(), static_cast<const float *>(uniform->pointer()));
00124      break;
00125 
00126     case Uniform::UT_FLOAT_3:
00127      glUniform3fv(Location, uniform->getActualLengthGPU(), static_cast<const float *>(uniform->pointer()));
00128      break;
00129    
00130    case Uniform::UT_FLOAT_4:
00131     glUniform4fv(Location, uniform->getActualLengthGPU(), static_cast<const float *>(uniform->pointer()));
00132     break;
00133 
00134 
00135     case Uniform::UT_MAT_2X2:
00136      glUniformMatrix2fv(Location, uniform->getActualLengthGPU(), false, static_cast<const float *>(uniform->pointer()));
00137      break;
00138 
00139     case Uniform::UT_MAT_3X3:
00140      glUniformMatrix3fv(Location, uniform->getActualLengthGPU(), false, static_cast<const float *>(uniform->pointer()));
00141      break;
00142 
00143     case Uniform::UT_MAT_4X4:
00144      glUniformMatrix4fv(Location, uniform->getActualLengthGPU(), false, static_cast<const float *>(uniform->pointer()));
00145      break;
00146 
00147     default:
00148      Except<ERR_NOT_IMPLEMENTED>(this, "Other uniform types not implemented.", "GLGLSLShader::setUniformVariable", __FILE__, __LINE__);
00149      break;
00150    }
00151 
00152    LogManager::getSingleton().logMessage(this, "Uniform variable \"" + uniform->getObjectName() + "\" successfuly set.", LML_Trivial);
00153   }
00154  }
00155 
00156 
00157  void GLGLSLShader::setUniformSampler(Uniform * uniform)
00158  {
00159   Texture * Sampler = uniform->getSampler();
00160   if (!Sampler->isUploadedToGPU())
00161   {
00162    Sampler->uploadToGPU();
00163   }
00164 
00165   GLint Location = getUniformLocation(Sampler->getObjectName());
00166   if (Location != -1)
00167   {
00168    glActiveTextureARB(GL_TEXTURE0_ARB + mMultiTextureNumber);
00169    Sampler->bind();
00170 
00171    glUniform1i(Location, mMultiTextureNumber);
00172    ++mMultiTextureNumber;
00173    LogManager::getSingleton().logMessage(this, "Uniform sampler \"" + uniform->getObjectName() + "\" successfully set.", LML_Trivial);
00174   }
00175  }
00176 
00177 
00178  void GLGLSLShader::compile(const std::string & Parameters)
00179  {
00180   // needs for recompilation shader
00181   mShaderCompilerParams = Parameters;
00182 
00183   LogManager::getSingleton().logMessage(this, "This type of shader cannot use compiler parameters. Following parameters will be ignored: \"" +
00184    Parameters + "\".", LML_Critical);
00185 
00186   const char * src = mShaderSource.c_str();
00187 
00188   glShaderSource(mGLSLFragmentShaderID, 1, &src, NULL);
00189   glCompileShader(mGLSLFragmentShaderID);
00190   compileStatus();
00191   LogManager::getSingleton().logMessage(this, "Shader compiled.", LML_Trivial);
00192 
00193   glLinkProgram(mGLSLProgramID);
00194   linkStatus();
00195   LogManager::getSingleton().logMessage(this, "Program linked.", LML_Trivial);
00196 
00197 
00198   if (LogManager::getSingleton().getLogDetail() == LL_Verbose)
00199   {
00200    ShaderInfoLog();
00201    ProgramInfoLog();
00202   }
00203   mIsCompiled = true;
00204  }
00205  
00206  
00207  void GLGLSLShader::preCompute()
00208  {
00209   if (!mIsCompiled)
00210   {
00211    compile(mShaderCompilerParams);
00212   }
00213 
00214   mMultiTextureNumber = 0;
00215   bind();
00216   for (UniformVector::iterator i = mUniformVector.begin(); i != mUniformVector.end(); ++i)
00217   {
00218    Uniform * uniform = (*i);
00219    Uniform::UniformType uniform_type = uniform->getUniformType();
00220    if ((uniform_type == Uniform::UT_TEX_1) || (uniform_type == Uniform::UT_TEX_2))
00221    {
00222     setUniformSampler(uniform);
00223    }
00224    else
00225    {
00226     setUniformVariable(uniform);
00227    }
00228   }
00229  }
00230 
00231 
00232  void GLGLSLShader::validate()
00233  {
00234   GLint validate_status = 0;
00235   glValidateProgram(mGLSLProgramID);
00236   glGetProgramiv(mGLSLProgramID, GL_VALIDATE_STATUS, &validate_status);
00237   if (validate_status != GL_TRUE)
00238   {
00239    Warning<ERR_SOURCE_COMPILATION_ERROR>(this, "Does not check validation!", "GLGLSLShader::validateShader", __FILE__, __LINE__);
00240    ProgramInfoLog();
00241   }
00242   else
00243   {
00244    LogManager::getSingleton().logMessage(this, "Validated, shader is ready for computation.", LML_Trivial);
00245   }
00247  }
00248 
00249 
00250  void GLGLSLShader::compileStatus()
00251  {
00252   GLint compile_status = 0;
00253   glGetShaderiv(mGLSLFragmentShaderID, GL_COMPILE_STATUS, &compile_status);
00254   if (compile_status != GL_TRUE)
00255   {
00256    ShaderInfoLog();
00257    Except<ERR_SOURCE_COMPILATION_ERROR>(this, "Cannot compile!", "GLGLSLShader::compileStatus()", __FILE__, __LINE__);
00258   }
00259  }
00260 
00261 
00262  void GLGLSLShader::ShaderInfoLog()
00263  {
00264   GLint infologLength = 0;
00265   GLint charsWritten  = 0;
00266   char * infoLog;
00267 
00268   glGetShaderiv(mGLSLFragmentShaderID, GL_INFO_LOG_LENGTH, &infologLength);
00269   if (infologLength > 1)
00270   {
00271    infoLog = new char [infologLength];
00272    glGetShaderInfoLog(mGLSLFragmentShaderID, infologLength, &charsWritten, infoLog);
00273    LogManager::getSingleton().logMessage(this, "Log of shader compilation:", LML_Critical);
00274    LogManager::getSingleton().logMessage(this, infoLog, LML_Critical);
00275    delete [] infoLog;
00276   }
00277  }
00278 
00279 
00280  void GLGLSLShader::linkStatus()
00281  {
00282   GLint link_status;
00283   glGetProgramiv(mGLSLProgramID, GL_LINK_STATUS, &link_status);
00284   if (link_status != GL_TRUE)
00285   {
00286    ProgramInfoLog();
00287    Except<ERR_SOURCE_COMPILATION_ERROR>(this, "Cannot link!", "GLGLSLShader::linkStatus()", __FILE__, __LINE__);
00288   }
00289  }
00290 
00291 
00292  void GLGLSLShader::ProgramInfoLog()
00293  {
00294   GLint infologLength = 0;
00295   GLint charsWritten  = 0;
00296   char * infoLog;
00297   glGetProgramiv(mGLSLProgramID, GL_INFO_LOG_LENGTH, &infologLength);
00298   if (infologLength > 1)
00299   {
00300    infoLog = new char [infologLength];
00301    glGetProgramInfoLog(mGLSLProgramID, infologLength, &charsWritten, infoLog);
00302    LogManager::getSingleton().logMessage(this, "Log of program compilation:", LML_Critical);
00303    LogManager::getSingleton().logMessage(this, infoLog, LML_Critical);
00304    delete [] infoLog;
00305   }
00306  }
00307 
00308 
00309  GLint GLGLSLShader::getUniformLocation(const std::string & Name)
00310  {
00311   GLint Result = glGetUniformLocation(mGLSLProgramID, Name.c_str());
00312   if (Result == -1)
00313   {
00314    Warning<ERR_ITEM_NOT_FOUND>(this, "Uniform variable \"" + Name + "\" cannot be found in shader", "GLGLSLShader::getUniformLocation", __FILE__, __LINE__);
00315   }
00316   return Result;
00317  }
00318 }

Generated on Thu Mar 5 22:36:42 2009 for gpucalc by  doxygen 1.5.6