BambooIsland: C:/Users/easterbunny/Desktop/Echtzeitgraphik-LU/trunk/src/Shader.cpp Source File

BambooIsland Abgabe 2

- Main Page
- Related Pages
- Classes
- Files

- File List

# C:/Users/easterbunny/Desktop/Echtzeitgraphik-LU/trunk/src/Shader.cpp

    00001 /*
    00002  * source file for Shadder class
    00003  * written by: christian moellinger <ch.moellinger@gmail.com>
    00004  * 10/2010
    00005  */
    00006
    00007 #include <iostream>
    00008 #include <fstream>
    00009 #include <cstdlib>
    00010
    00011 #include "common_gl.h"
    00012 #include "Logger.h"
    00013 #include "Shader.h"
    00014
    00015 using namespace std;
    00016
    00017 int last_active;
    00018
    00020 bool loadShaderToString(const char* filename, GLubyte** ShaderSource, unsigned long* len)
    00021 {
    00022     ifstream file;
    00023     file.open(filename, ios::in); // opens as ASCII!
    00024
    00025     if(!file)
    00026     {
    00027         Logger::instance()->log(Logger::FATAL, string("Could not read shader source code from ") + string(filename));
    00028         return false;
    00029     }
    00030
    00031     if(!file.good())
    00032     {
    00033         Logger::instance()->log(Logger::FATAL, string("Could not read shader source code from ") + string(filename));
    00034         return false;
    00035     }
    00036
    00037     unsigned long pos=file.tellg();
    00038     file.seekg(0,ios::end);
    00039     *len = file.tellg();
    00040     file.seekg(ios::beg);
    00041
    00042     if (*len==0)
    00043     {
    00044         Logger::instance()->log(Logger::FATAL, string("Could not read shader source code from ") + string(filename) + string(" (File was empty)"));
    00045         return false;
    00046     }
    00047
    00048     *ShaderSource = (GLubyte*) new GLubyte[(*len)+1];
    00049
    00050     if (*ShaderSource == 0)
    00051     {
    00052         Logger::instance()->log(Logger::FATAL, string("Could not reserve memory for shader source code (reading ") + string(filename) + string(")"));
    00053         return false;
    00054     }
    00055
    00056     // len isn't always strlen cause some characters are stripped in ascii read...
    00057     // it is important to 0-terminate the real length later, len is just max possible value...
    00058     (*ShaderSource)[*len] = 0;
    00059
    00060     unsigned int i=0;
    00061     while (file.good())
    00062     {
    00063        (*ShaderSource)[i] = file.get();       // get character from file.
    00064        if (!file.eof())
    00065         i++;
    00066     }
    00067
    00068     (*ShaderSource)[i] = 0;  // 0-terminate it at the correct position
    00069
    00070     file.close();
    00071
    00072     return true;
    00073 }
    00074
    00076 void printShaderLog(GLuint obj)
    00077 {
    00078     int infologLength = 0;
    00079     int maxLength=0;
    00080
    00081     if(glIsShader(obj))
    00082             glGetShaderiv(obj,GL_INFO_LOG_LENGTH,&maxLength);
    00083     else
    00084             glGetProgramiv(obj,GL_INFO_LOG_LENGTH,&maxLength);
    00085
    00086     char *infoLog = new char[maxLength];
    00087
    00088     if (glIsShader(obj))
    00089             glGetShaderInfoLog(obj, maxLength, &infologLength, infoLog);
    00090     else
    00091             glGetProgramInfoLog(obj, maxLength, &infologLength, infoLog);
    00092
    00093     if (infologLength > 1)
    00094         Logger::instance()->log(Logger::DEBUG, string("Shader messages: \n") + string(infoLog));
    00095
    00096     delete[] infoLog;
    00097 }
    00098
    00099 Shader::Shader(const char *vertexshader_filename, const char *fragmentshader_filename, const char *geometryshader_filename) : m_bReadyForUse(false)
    00100 {
    00101         bool hasGeometryShader = false;
    00102         if (geometryshader_filename!=0){
    00103                 hasGeometryShader = true;
    00104         }
    00105
    00106     GLubyte *vertexshader_source = 0;
    00107         GLubyte *geometryshader_source = 0;
    00108     GLubyte *fragmentshader_source = 0;
    00109
    00110     unsigned long int vertexshader_length;
    00111         unsigned long int geometryshader_length;
    00112     unsigned long int fragmentshader_length;
    00113
    00114         if (hasGeometryShader)
    00115                 Logger::instance()->log(Logger::TRACE, string("Initializing shader object, given filenames: ") + string(vertexshader_filename) + string(" and ") + string(geometryshader_filename) + string(" and ") + string(fragmentshader_filename));
    00116         else
    00117                 Logger::instance()->log(Logger::TRACE, string("Initializing shader object, given filenames: ") + string(vertexshader_filename) + string(" and ") + string(fragmentshader_filename));
    00118
    00119     //load shaders to char *
    00120     bool vs_source_ok = false;
    00121         bool gs_source_ok = false;
    00122         bool fs_source_ok = false;
    00123
    00124         vs_source_ok = loadShaderToString(vertexshader_filename, &vertexshader_source, &vertexshader_length);
    00125         if (hasGeometryShader)
    00126                 gs_source_ok = loadShaderToString(geometryshader_filename, &geometryshader_source, &geometryshader_length);
    00127     fs_source_ok = loadShaderToString(fragmentshader_filename, &fragmentshader_source, &fragmentshader_length);
    00128
    00129     if ( ((vs_source_ok != 0) && (fs_source_ok != 0) && (!hasGeometryShader)) || ((vs_source_ok != 0) && (fs_source_ok != 0) && (gs_source_ok !=0) ))
    00130     {
    00131         GLuint vertexShaderObject, fragmentShaderObject;
    00132         GLuint geometryShaderObject;
    00133
    00134         //create shader objects, fetch ids
    00135         vertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
    00136         if (hasGeometryShader) geometryShaderObject = glCreateShader(GL_GEOMETRY_SHADER);
    00137         fragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
    00138
    00139         //load shader source in objects
    00140         glShaderSource(vertexShaderObject, 1,  (const GLchar **) &vertexshader_source, (const GLint *) &vertexshader_length);
    00141         if (hasGeometryShader) glShaderSource(geometryShaderObject, 1, (const GLchar **) &geometryshader_source, (const GLint *) &geometryshader_length);
    00142         glShaderSource(fragmentShaderObject, 1,  (const GLchar **) &fragmentshader_source, (const GLint *) &fragmentshader_length);
    00143
    00144         //compile shader objects
    00145         glCompileShader(vertexShaderObject);
    00146         if (hasGeometryShader) glCompileShader(geometryShaderObject);
    00147         glCompileShader(fragmentShaderObject);
    00148
    00149         //lets see if an error happened
    00150         GLint compiled;
    00151
    00152         //check vertex shader object
    00153         glGetShaderiv(vertexShaderObject, GL_COMPILE_STATUS, &compiled);
    00154         if (!compiled)
    00155         {
    00156             printShaderLog(vertexShaderObject);
    00157             Logger::instance()->log(Logger::FATAL, "Could not compile vertex shader");
    00158         }
    00159
    00160         // check geometry shader object
    00161         if (hasGeometryShader){
    00162                 glGetShaderiv(geometryShaderObject, GL_COMPILE_STATUS, &compiled);
    00163                 if (!compiled)
    00164                 {
    00165                         printShaderLog(geometryShaderObject);
    00166                         Logger::instance()->log(Logger::FATAL, "Could not compile geometry shader");
    00167                 }
    00168         }
    00169         //check fragment shader object
    00170         glGetShaderiv(fragmentShaderObject, GL_COMPILE_STATUS, &compiled);
    00171         if (!compiled)
    00172         {
    00173             printShaderLog(fragmentShaderObject);
    00174             Logger::instance()->log(Logger::FATAL, "Could not compile fragment shader");
    00175         }
    00176
    00177         GLuint ProgramObject = glCreateProgram();
    00178
    00179         glAttachShader(ProgramObject, vertexShaderObject);
    00180         if (hasGeometryShader) glAttachShader(ProgramObject, geometryShaderObject);
    00181         glAttachShader(ProgramObject, fragmentShaderObject);
    00182
    00183         glLinkProgram(ProgramObject);
    00184
    00185         GLint linked;
    00186         glGetProgramiv(ProgramObject, GL_LINK_STATUS, &linked);
    00187
    00188         if (!linked)
    00189         {
    00190            printShaderLog(ProgramObject);
    00191            Logger::instance()->log(Logger::FATAL, "Could not link shader program");
    00192         }
    00193         else
    00194         {
    00195                 if (hasGeometryShader)
    00196                         Logger::instance()->log(Logger::DEBUG, string("Successfully compiled and linked ") + string(vertexshader_filename) + string(" and ") + string(geometryshader_filename) + string(" and ") + string (fragmentshader_filename) + string(" to a shader object"));
    00197                 else
    00198                         Logger::instance()->log(Logger::DEBUG, string("Successfully compiled and linked ") + string(vertexshader_filename) + string(" and ") + string (fragmentshader_filename) + string(" to a shader object"));
    00199
    00200                 this->m_nShaderId = ProgramObject;
    00201                 this->m_bReadyForUse = true;
    00202         }
    00203     }
    00204     else
    00205     {
    00206         Logger::instance()->log(Logger::FATAL, "Could not initialize shader program");
    00207     }
    00208
    00209     //free used (GLubyte) arrays
    00210     if (vertexshader_source != 0)
    00211         delete[] vertexshader_source;
    00212
    00213         if (hasGeometryShader){
    00214                 if (geometryshader_source != 0)
    00215                         delete[] geometryshader_source;
    00216         }
    00217
    00218     if (fragmentshader_source != 0)
    00219         delete[] fragmentshader_source;
    00220 }
    00221
    00222
    00223 Shader::~Shader()
    00224 {
    00225     //todo: clear up used program ids and shader ids?
    00226 }
    00227
    00228 void Shader::activate()
    00229 {
    00230     //activate shader if it is ready for use, else log an error message
    00231
    00232     if (this->m_bReadyForUse)
    00233     {
    00234         glGetError();
    00235
    00236         glUseProgram(this->m_nShaderId);
    00237
    00238         GLenum error = glGetError();
    00239         if (error != GL_NO_ERROR)
    00240             Logger::instance()->log(Logger::ERROR, translateGLerror(error));
    00241
    00242         last_active = this->m_nShaderId;
    00243     }
    00244     else
    00245         Logger::instance()->log(Logger::ERROR, "Could not activate shader because it is not ready for use");
    00246 }
    00247
    00248 GLint Shader::getUniformLocation(const char *name)
    00249 {
    00250     if (last_active != this->m_nShaderId)
    00251         Logger::instance()->log(Logger::WARN, string("While setting an uniform of an shader, the shader must be active!"));
    00252
    00253     GLint location = glGetUniformLocation(this->m_nShaderId, name);
    00254
    00255     return location;
    00256 }
    00257
    00258 GLint Shader::getAttribLocation(const char *name)
    00259 {
    00260     if (last_active != this->m_nShaderId)
    00261         Logger::instance()->log(Logger::WARN, string("While setting an attribute of an shader, the shader must be active!"));
    00262
    00263     GLint location = glGetAttribLocation(this->m_nShaderId, name);
    00264
    00265     return location;
    00266 }

All Classes Functions Variables Enumerations Enumerator