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