$search
00001 /* Shader 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/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 //dumpVars(); 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 //ROS_DEBUG("f: %f %f %f\n", f[0],f[1],f[2]); 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