00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
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
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
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