tgShader.cpp
Go to the documentation of this file.
00001 /* tgShader
00002  *
00003  * Copyright (C) 2005, Maurizio Monge <maurizio.monge@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 Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #include <blort/TomGine/tgShader.h>
00021 #include <string.h>
00022 #include <stdarg.h>
00023 #include <stdexcept>
00024 
00025 #ifdef HAVE_GTK
00026 #include <gtk/gtk.h>
00027 #endif
00028 
00029 #include <GL/glu.h>
00030 
00031 using namespace TomGine;
00032 
00033 static const char *gl_type_name(GLenum type)
00034 {
00035     switch(type)
00036     {
00037         case GL_FLOAT:             return "float";
00038         case GL_FLOAT_VEC2_ARB:    return "vec2";
00039         case GL_FLOAT_VEC3_ARB:    return "vec3";
00040         case GL_FLOAT_VEC4_ARB:    return "vec4";
00041         case GL_FLOAT_MAT2_ARB:    return "mat2";
00042         case GL_FLOAT_MAT3_ARB:    return "mat3";
00043         case GL_FLOAT_MAT4_ARB:    return "mat4";
00044         case GL_INT:               return "int";
00045         case GL_INT_VEC2_ARB:      return "ivec2";
00046         case GL_INT_VEC3_ARB:      return "ivec3";
00047         case GL_INT_VEC4_ARB:      return "ivec4";
00048         case GL_BOOL_ARB:          return "bool";
00049         case GL_BOOL_VEC2_ARB:     return "bvec2";
00050         case GL_BOOL_VEC3_ARB:     return "bvec3";
00051         case GL_BOOL_VEC4_ARB:     return "bvec4";
00052         case GL_SAMPLER_1D:        return "sampler1D";
00053         case GL_SAMPLER_2D:        return "sampler2D";
00054         case GL_SAMPLER_3D:        return "sampler3D";
00055         case GL_SAMPLER_CUBE:      return "samplerCube";
00056         case GL_SAMPLER_1D_SHADOW: return "sampler1DShadow";
00057         case GL_SAMPLER_2D_SHADOW: return "sampler2DShadow";
00058         default:
00059         {
00060             static char tmp[64];
00061             snprintf(tmp,64,"?0x%x?", type );
00062             return tmp;
00063         }
00064     }
00065 }
00066 
00067 void tgShader::dumpVars()
00068 {
00069     int nv;
00070     glGetObjectParameterivARB( program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &nv);
00071     printf("UNIFORM variables (%d):\n",nv);
00072 
00073     for(int i=0;i<nv;i++)
00074     {
00075         GLenum type;
00076         int size;
00077         char vname[4096];
00078         glGetActiveUniformARB(program,i,4096,NULL,&size,&type,vname);
00079         printf("  %s %s;\n", gl_type_name(type),vname);
00080     }
00081 
00082     glGetObjectParameterivARB( program, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &nv);
00083     printf("ATTRIBUTE variables (%d):\n",nv);
00084     for(int i=0;i<nv;i++)
00085     {
00086         GLenum type;
00087         int size;
00088         char vname[4096];
00089         glGetActiveAttribARB(program,i,4096,NULL,&size,&type,vname);
00090         printf("  %s %s;\n", gl_type_name(type),vname);
00091     }
00092 }
00093 
00094 void tgShader::printInfoLog(GLhandleARB obj, const char *msg, ...)
00095 {
00096     int infologLength = 0;
00097     int charsWritten  = 0;
00098     char *infoLog;
00099 
00100     glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
00101                               &infologLength);
00102     if(infologLength > 1)
00103     {
00104         va_list va;
00105         va_start(va, msg);
00106         infoLog = (char *)malloc(infologLength);
00107         glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
00108 #ifdef HAVE_GTK
00109         char *m = g_strdup_vprintf(msg, va);
00110         GtkWidget *dialog = gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,
00111                 GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,"%s (%d):",m,infologLength);
00112         g_free(m);
00113         gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),"%s",infoLog);
00114         gtk_dialog_run(GTK_DIALOG(dialog));
00115         gtk_widget_destroy(dialog);
00116 #else
00117         vprintf(msg, va);
00118         printf(" (%d):\n",infologLength);
00119         printf("%s",infoLog);
00120 #endif
00121         va_end(va);
00122         free(infoLog);
00123     }
00124 }
00125 
00126 bool tgShader::getStatus(){
00127     if(program)
00128         return true;
00129     
00130     return false;
00131 }
00132 
00133 tgShader::tgShader(const char *vertex_file, const char *fragment_file, const char *header)
00134 {
00135     GLint status;
00136     const char *vs = read_text_file(vertex_file);
00137     const char *fs = read_text_file(fragment_file);
00138 
00139     char charbuffer[512];
00140         
00141         if( vertex_file && !vs ){
00142                 sprintf(charbuffer, "[tgShader::tgShader] Error loading file for vertex shader '%s'.", vertex_file);
00143                 throw std::runtime_error(charbuffer);
00144         }
00145 
00146         
00147         if( fragment_file && !fs ){
00148                 sprintf(charbuffer, "[tgShader::tgShader] Error loading file for fragment shader '%s'.", fragment_file);
00149                 throw std::runtime_error(charbuffer);
00150         }
00151     
00152         if(header)  {
00153         if(vs) {
00154             char *tmp = (char*)malloc(strlen(header)+strlen(vs)+1);
00155             strcpy(tmp,header);
00156             strcat(tmp,vs);
00157             free((void*)vs);
00158             vs = tmp;
00159         }
00160         if(fs) {
00161             char *tmp = (char*)malloc(strlen(header)+strlen(fs)+1);
00162             strcpy(tmp,header);
00163             strcat(tmp,fs);
00164             free((void*)fs);
00165             fs = tmp;
00166         }
00167     }
00168 
00169     if(vs)
00170     {
00171         vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
00172         glShaderSourceARB(vertex, 1, &vs, NULL);
00173         glCompileShaderARB(vertex);
00174 
00175         glGetObjectParameterivARB( vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status);
00176         if(!status)
00177         {
00178             printInfoLog(vertex,"[tgShader::tgShader] Error compiling vertex shader \"%s\"",vertex_file);
00179             program = 0;
00180             return;
00181         }
00182         free((void*)vs);
00183     }
00184     else
00185         vertex = 0;
00186 
00187     if(fs)
00188     {
00189         fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
00190         glShaderSourceARB(fragment, 1, &fs,NULL);
00191         glCompileShaderARB(fragment);
00192 
00193         glGetObjectParameterivARB( fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status);
00194         if(!status)
00195         {
00196             printInfoLog(fragment,"[tgShader::tgShader] Error compiling fragment shader \"%s\"",fragment_file);
00197             program = 0;
00198             return;
00199         }
00200         free((void*)fs);
00201     }
00202     else
00203         fragment = 0;
00204 
00205     if(fragment==0 && vertex==0)
00206     {
00207         program = 0;
00208         return;
00209     }
00210 
00211     program = glCreateProgramObjectARB();
00212     if(vertex!=0)
00213     {
00214         glAttachObjectARB(program,vertex);
00215         glDeleteObjectARB(vertex);
00216     }
00217     if(fragment!=0)
00218     {
00219         glAttachObjectARB(program,fragment);
00220         glDeleteObjectARB(fragment);
00221     }
00222     glLinkProgramARB(program);
00223 
00224     glGetObjectParameterivARB( program, GL_OBJECT_LINK_STATUS_ARB, &status);
00225     if(!status)
00226     {
00227         printInfoLog(program,"Error linking program with \"%s\" and \"%s\"",
00228                                                     vertex_file,fragment_file);
00229         glDeleteObjectARB(program);
00230         program = 0;
00231         return;
00232     }
00233 
00234     glValidateProgramARB(program);
00235     glGetObjectParameterivARB( program, GL_OBJECT_VALIDATE_STATUS_ARB,&status);
00236     printInfoLog(program,"%s validating program",status?"Information":"Error");
00237     if(!status)
00238     {
00239         glDeleteObjectARB(program);
00240         program = 0;
00241     }
00242 
00243     //dumpVars();
00244 }
00245 
00246 tgShader::~tgShader()
00247 {
00248     if(program!=0){
00249         glDeleteObjectARB(program);
00250     }
00251 }
00252 
00253 void tgShader::bind()
00254 {
00255     if(program)
00256         glUseProgramObjectARB(program);
00257 }
00258 
00259 void tgShader::unbind()
00260 {
00261     if(program)
00262         glUseProgramObjectARB(0);
00263 }
00264 
00265 GLuint tgShader::getAttribLoc(const char *attr)
00266 {
00267     return glGetAttribLocationARB( program, attr);
00268 }
00269 
00270 GLint tgShader::getUniformLoc(const char* var)
00271 {
00272     return glGetUniformLocationARB(program,var);
00273 }
00274 
00275 void tgShader::setUniform(const char* var,int f)
00276 {
00277     int loc = glGetUniformLocationARB(program,var);
00278     glUniform1iARB(loc,f);
00279 }
00280 
00281 void tgShader::setUniform(const char* var,unsigned f)
00282 {
00283     int loc = glGetUniformLocationARB(program,var);
00284     glUniform1iARB(loc,(int)f);
00285 }
00286 
00287 void tgShader::setUniform(const char* var,int n,const int* f)
00288 {
00289     int loc = glGetUniformLocationARB(program,var);
00290     glUniform1ivARB(loc,n,f);
00291 }
00292 
00293 void tgShader::setUniform(const char* var,float f)
00294 {
00295     int loc = glGetUniformLocationARB(program,var);
00296     glUniform1fARB(loc,f);
00297 }
00298 
00299 void tgShader::setUniform(const char* var,int n,const float* f)
00300 {
00301     int loc = glGetUniformLocationARB(program,var);
00302     glUniform1fvARB(loc,n,f);
00303     //printf("f: %f %f %f\n", f[0],f[1],f[2]);
00304 }
00305 
00306 void tgShader::setUniform(const char* var,vec2 f)
00307 {
00308     int loc = glGetUniformLocationARB(program,var);
00309     glUniform2fvARB(loc,1,f.v);
00310 }
00311 
00312 void tgShader::setUniform(const char* var,int n,vec2* f)
00313 {
00314     int loc = glGetUniformLocationARB(program,var);
00315     glUniform1fvARB(loc,2*n,f->v);
00316 }
00317 
00318 void tgShader::setUniform(const char* var,vec3 f)
00319 {
00320     int loc = glGetUniformLocationARB(program,var);
00321     glUniform3fvARB(loc,1,f.v);
00322 }
00323 
00324 void tgShader::setUniform(const char* var,int n,vec3* f)
00325 {
00326     int loc = glGetUniformLocationARB(program,var);
00327     glUniform1fvARB(loc,3*n,f->v);
00328 }
00329 
00330 void tgShader::setUniform(const char* var,vec4 f)
00331 {
00332     int loc = glGetUniformLocationARB(program,var);
00333     glUniform4fv(loc,1,f.v);
00334 }
00335 
00336 void tgShader::setUniform(const char* var,int n,vec4* f)
00337 {
00338     int loc = glGetUniformLocationARB(program,var);
00339     glUniform1fvARB(loc,4*n,f->v);
00340 }
00341 
00342 void tgShader::setUniform(const char* var,mat3 f,bool transpose)
00343 {
00344     int loc = glGetUniformLocationARB(program,var);
00345     glUniformMatrix3fvARB(loc,1,transpose,f.mat);
00346 }
00347 
00348 void tgShader::setUniform(const char* var,int n,mat3* f,bool transpose)
00349 {
00350     int loc = glGetUniformLocationARB(program,var);
00351     glUniformMatrix3fvARB(loc,n,transpose,f->mat);
00352 }
00353 
00354 void tgShader::setUniform(const char* var,mat4 f,bool transpose)
00355 {
00356     int loc = glGetUniformLocationARB(program,var);
00357     glUniformMatrix4fvARB(loc,1,transpose,f.mat);
00358 }
00359 
00360 void tgShader::setUniform(const char* var,int n,mat4* f,bool transpose)
00361 {
00362     int loc = glGetUniformLocationARB(program,var);
00363     glUniformMatrix4fvARB(loc,n,transpose,f->mat);
00364 }
00365 
00366 void* TomGine::malloc_align(size_t size, int align)
00367 {
00368     char *tmp = (char*)malloc(size+align-1+sizeof(void*));
00369     char *addr = tmp+align-1+sizeof(void*);
00370     addr -= (long)addr & (align-1);
00371     ((void**)addr)[-1] = tmp;
00372     return addr;
00373 }
00374 
00375 void TomGine::free_align(void *addr)
00376 {
00377     void *tmp = ((void**)addr)[-1];
00378     free(tmp);
00379 }
00380 
00381 char* TomGine::read_text_file(const char* file)
00382 {
00383     if(!file) return NULL;
00384 
00385     FILE *f = fopen(file ,"r");
00386     if(!f) return NULL;
00387 
00388     fseek(f, 0, SEEK_END);
00389     int sz = ftell(f);
00390     fseek(f, 0, SEEK_SET);
00391 
00392     char *retv = (char*)malloc(sz+1);
00393     const size_t size = fread(retv, sz, 1, f);
00394     retv[sz] = size;
00395     retv[sz] = 0;
00396     fclose(f);
00397 
00398     return retv;
00399 }
00400 


blort
Author(s): Michael Zillich, Thomas Mörwald, Johann Prankl, Andreas Richtsfeld, Bence Magyar (ROS version)
autogenerated on Thu Jan 2 2014 11:38:26