GLSLShader.cc

00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                              OpenFlipper                                  *
00004  *      Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openflipper.org                             *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------*
00008  *  This file is part of OpenFlipper.                                        *
00009  *                                                                           *
00010  *  OpenFlipper is free software: you can redistribute it and/or modify      *
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenFlipper is distributed in the hope that it will be useful,           *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenFlipper. If not,                                  *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/
00034 
00035 /*===========================================================================*\
00036  *                                                                           *
00037  *   $Revision: 6743 $                                                       *
00038  *   $Author: moebius $                                                      *
00039  *   $Date: 2009-08-05 11:03:10 +0200 (Mi, 05. Aug 2009) $                   *
00040  *                                                                           *
00041 \*===========================================================================*/
00042 
00043 /*******************************************************************************
00044  * GLSLShader.h
00045  *
00046  * Utility classes for GLSL shaders.
00047  *
00048  * (C)2007
00049  * Lehrstuhl I8 RWTH-Aachen, http://www-i8.informatik.rwth-aachen.de
00050  * Author: Markus Tavenrath <speedygoo@speedygoo.de>
00051  *
00052  ******************************************************************************/
00053 
00054 //==============================================================================
00055 
00056 #include <QApplication>
00057 #include <QDir>
00058 #include <QString>
00059 
00060 #include <iostream>
00061 #include <cassert>
00062 #include <sstream>
00063 #include <fstream>
00064 
00065 #include <../GL/gl.hh>
00066 
00067 #include "gldebug.h"
00068 #include "GLSLShader.hh"
00069 
00070 #ifdef WIN32
00071 #define snprintf sprintf_s
00072 #endif
00073 
00074 //==============================================================================
00075 
00076 namespace GLSL {
00077 
00078     //--------------------------------------------------------------------------
00079     // Generic shader
00080     //--------------------------------------------------------------------------
00081 
00086     Shader::Shader(GLenum shaderType)
00087         : m_shaderId(0)
00088     {
00089         this->m_shaderId = glCreateShader(shaderType);
00090         assert(this->m_shaderId && "could not create shader");
00091     }
00092 
00095     Shader::~Shader()
00096     {
00097         if (this->m_shaderId) {
00098             glDeleteShader(m_shaderId);
00099         }
00100     }
00101 
00104     void Shader::setSource(StringList source)
00105     {
00106         assert(this->m_shaderId && "shader not initialized");
00107 
00108         const char **stringArray = new const char*[source.size()];
00109 
00110         int index = 0;
00111         for (StringList::const_iterator it = source.begin();it != source.end();++it) {
00112             stringArray[index] = (*it).c_str();
00113             ++index;
00114         }
00115 
00116         glShaderSource(this->m_shaderId, source.size(), stringArray, 0);
00117 
00118         delete[] stringArray;
00119     }
00120 
00126     bool Shader::compile()
00127     {
00128         assert(this->m_shaderId && "shader not initialized");
00129 
00130         glCompileShader(this->m_shaderId);
00131 
00132         GLint compileStatus;
00133         glGetShaderiv(this->m_shaderId, GL_COMPILE_STATUS, &compileStatus);
00134         if (compileStatus == GL_FALSE) {
00135             GLchar *errorLog = new GLchar[GLSL_MAX_LOGSIZE];
00136             GLsizei errorLength;
00137             char shaderSource[32768];
00138             glGetShaderSource(this->m_shaderId, 32768, &errorLength, shaderSource);
00139             std::cout << "shader source: " << std::endl << shaderSource << std::endl;
00140             glGetShaderInfoLog(this->m_shaderId, GLSL_MAX_LOGSIZE, &errorLength, errorLog);
00141             std::cout << "GLSL compile error:" << std::endl << errorLog << std::endl;
00142             delete[] errorLog;
00143 
00144             return false;
00145         }
00146         return true;
00147     }
00148 
00149     //--------------------------------------------------------------------------
00150     // Vertex shader
00151     //--------------------------------------------------------------------------
00152 
00153     VertexShader::VertexShader() : Shader(GL_VERTEX_SHADER) {}
00154     VertexShader::~VertexShader() {}
00155 
00156     //--------------------------------------------------------------------------
00157     // Fragment shader
00158     //--------------------------------------------------------------------------
00159 
00160     FragmentShader::FragmentShader() : Shader(GL_FRAGMENT_SHADER) {}
00161     FragmentShader::~FragmentShader() {}
00162 
00163     //--------------------------------------------------------------------------
00164     // Shader program object
00165     //--------------------------------------------------------------------------
00166 
00169     Program::Program()
00170     {
00171         this->m_programId = glCreateProgram();
00172         assert(this->m_programId && "could not create GLSL program");
00173     }
00174 
00177     Program::~Program()
00178     {
00179         if (this->m_programId) {
00180             glDeleteProgram(this->m_programId);
00181         }
00182         // free linked shaders
00183         this->m_linkedShaders.clear();
00184     }
00185 
00188     void
00189     Program::attach(PtrConstShader shader)
00190     {
00191         assert(this->m_programId && "attach invalid program");
00192         assert(shader->m_shaderId && "attach invalid shader");
00193 
00194         glAttachShader(this->m_programId, shader->m_shaderId);
00195         m_linkedShaders.push_back(shader);
00196     }
00197 
00200     void Program::detach(PtrConstShader shader)
00201     {
00202         assert(this->m_programId && "detach invalid program");
00203         assert(shader->m_shaderId && "detach invalid shader");
00204 
00205         glDetachShader(this->m_programId, shader->m_shaderId);
00206         m_linkedShaders.remove(shader);
00207     }
00208 
00211     void Program::link()
00212     {
00213         glLinkProgram(this->m_programId);
00214         checkGLError2("link program failed");
00215     }
00216 
00219     void Program::use()
00220     {
00221         glUseProgram(this->m_programId);
00222         checkGLError2("use program failed");
00223     }
00224 
00227     void Program::disable() {
00228         glUseProgram(0);
00229         checkGLError2("shader disable failed");
00230     }
00231 
00234     bool Program::isActive()
00235     {
00236         GLint programId;
00237         glGetIntegerv(GL_CURRENT_PROGRAM, &programId);
00238         return programId == this->m_programId;
00239     }
00240 
00243     void Program::setUniform(const char *name, GLint value)
00244     {
00245         checkGLError();
00246         GLint location = glGetUniformLocation(this->m_programId, name);
00247         checkGLError2(name);
00248         glUniform1i(location, value);
00249         checkGLError2(name);
00250     }
00251 
00254     void Program::setUniform(const char *name, GLfloat value)
00255     {
00256         checkGLError2("prev opengl error");
00257         GLint location = glGetUniformLocation(this->m_programId, name);
00258         checkGLError2(name);
00259         glUniform1f(location, value);
00260         checkGLError2(name);
00261     }
00262 
00265     void Program::setUniform(const char *name, const ACG::Vec3f &value)
00266     {
00267         checkGLError();
00268         GLint location = glGetUniformLocation(this->m_programId, name);
00269         checkGLError2(name);
00270         glUniform3fv(location, 1, value.data());
00271         checkGLError();
00272     }
00273 
00274     void Program::setUniform(const char *name, GLint *values, int count)
00275     {
00276         checkGLError();
00277         GLint location = glGetUniformLocation(this->m_programId, name);
00278         checkGLError2(name);
00279         glUniform1iv(location, count, values);
00280         checkGLError();
00281     }
00282 
00283     void Program::setUniform(const char *name, int index, bool value)
00284     {
00285         char varName[1024];
00286         snprintf(varName, 1024, "%s[%d]", name, index);
00287         setUniform(varName, (GLint) value);
00288     }
00289 
00290     void Program::setUniform(const char *name, int index, int value)
00291     {
00292         char varName[1024];
00293         snprintf(varName, 1024, "%s[%d]", name, index);
00294         setUniform(varName, (GLint) value);
00295     }
00296 
00297     void Program::setUniform(const char *name, int index, float value)
00298     {
00299         char varName[1024];
00300         snprintf(varName, 1024, "%s[%d]", name, index);
00301         setUniform(varName, value);
00302     }
00303 
00304     void Program::bindAttributeLocation(unsigned int index, const char *name) {
00305         glBindAttribLocation(this->m_programId, index, name);
00306         checkGLError2(name);
00307     }
00308 
00309     int Program::getAttributeLocation(const char *name) {
00310         int attributeLocation = glGetAttribLocationARB(this->m_programId, name);
00311         checkGLError2(name);
00312         return attributeLocation;
00313     }
00314 
00315     int Program::getUniformLocation(const char *name) {
00316         int attributeLocation = glGetUniformLocationARB(this->m_programId, name);
00317         checkGLError2(name);
00318         return attributeLocation;
00319     }
00320 
00328     GLSL::StringList loadShader(const char *filename)
00329     {
00330         QString path_file;
00331         if (QDir(filename).isRelative()) {
00332             path_file = qApp->applicationDirPath() + QString("/../shader/")
00333                 + QString(filename);
00334         } else {
00335             path_file = QString::fromAscii(filename);
00336         }
00337         std::ifstream iShader(path_file.toAscii());
00338         if (!iShader) {
00339             std::cout << "ERROR: Could not open file " << path_file.toStdString() << std::endl;
00340             return GLSL::StringList();
00341         }
00342 
00343         GLSL::StringList shaderSource;
00344 
00345         while (!iShader.eof()) {
00346             std::string strLine;
00347             std::getline(iShader, strLine);
00348             strLine += "\n";
00349             shaderSource.push_back(strLine);
00350         }
00351         iShader.close();
00352         return shaderSource;
00353     }
00354 
00357     GLSL::PtrVertexShader loadVertexShader(const char *name)
00358     {
00359         PtrVertexShader vertexShader = 0;
00360         StringList sourceVertex = loadShader(name);
00361 
00362         if (sourceVertex.size() != 0) {
00363             vertexShader = GLSL::PtrVertexShader(new GLSL::VertexShader());
00364             vertexShader->setSource(sourceVertex);
00365             vertexShader->compile();
00366         }
00367         return vertexShader;
00368     }
00369 
00372     GLSL::PtrFragmentShader loadFragmentShader(const char *name)
00373     {
00374         PtrFragmentShader fragmentShader = 0;
00375         StringList sourceVertex = loadShader(name);
00376 
00377         if (sourceVertex.size() != 0) {
00378             fragmentShader = GLSL::PtrFragmentShader(new GLSL::FragmentShader());
00379             fragmentShader->setSource(sourceVertex);
00380             fragmentShader->compile();
00381         }
00382         return fragmentShader;
00383     }
00384 
00385 }
00386 
00387 
00388 //==============================================================================
00389 
00390 // Local Variables:
00391 // mode: C++
00392 // c-basic-offset: 4
00393 // indent-tabs-mode: nil
00394 // End:
00395 
00396 //==============================================================================

acg pic Project OpenFlipper, ©  Computer Graphics Group, RWTH Aachen. Documentation generated using doxygen .