shader.cpp

00001 /* Shader
00002  *
00003  * Copyright (C) 2003-2005, Alexander Zaprjagaev <frustum@frustum.org>
00004  *                          Roman Grigoriev <grigoriev@gosniias.ru>
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  */
00020 
00021 #include <cstring>
00022 #include <stdlib.h>
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #  include <simgear_config.h>
00026 #endif 
00027 
00028 #include <simgear/debug/logstream.hxx>
00029 #include "shader.h"
00030 #include <stdio.h>
00031 #include <stdarg.h>
00032 
00033 
00034 glVertexAttrib1dProc glVertexAttrib1dPtr = NULL;
00035 glVertexAttrib1dvProc glVertexAttrib1dvPtr = NULL;
00036 glVertexAttrib1fProc glVertexAttrib1fPtr = NULL;
00037 glVertexAttrib1fvProc glVertexAttrib1fvPtr = NULL;
00038 glVertexAttrib1sProc glVertexAttrib1sPtr  = NULL;
00039 glVertexAttrib1svProc glVertexAttrib1svPtr  = NULL;
00040 glVertexAttrib2dProc glVertexAttrib2dPtr  = NULL;
00041 glVertexAttrib2dvProc glVertexAttrib2dvPtr  = NULL;
00042 glVertexAttrib2fProc glVertexAttrib2fPtr  = NULL;
00043 glVertexAttrib2fvProc glVertexAttrib2fvPtr  = NULL;
00044 glVertexAttrib2sProc glVertexAttrib2sPtr  = NULL;
00045 glVertexAttrib2svProc glVertexAttrib2svPtr  = NULL;
00046 glVertexAttrib3dProc glVertexAttrib3dPtr  = NULL;
00047 glVertexAttrib3dvProc glVertexAttrib3dvPtr  = NULL;
00048 glVertexAttrib3fProc glVertexAttrib3fPtr  = NULL;
00049 glVertexAttrib3fvProc glVertexAttrib3fvPtr  = NULL;
00050 glVertexAttrib3sProc glVertexAttrib3sPtr  = NULL;
00051 glVertexAttrib3svProc glVertexAttrib3svPtr  = NULL;
00052 glVertexAttrib4NbvProc glVertexAttrib4NbvPtr  = NULL;
00053 glVertexAttrib4NivProc glVertexAttrib4NivPtr  = NULL;
00054 glVertexAttrib4NsvProc glVertexAttrib4NsvPtr  = NULL;
00055 glVertexAttrib4NubProc glVertexAttrib4NubPtr  = NULL;
00056 glVertexAttrib4NubvProc glVertexAttrib4NubvPtr  = NULL;
00057 glVertexAttrib4NuivProc glVertexAttrib4NuivPtr  = NULL;
00058 glVertexAttrib4NusvProc glVertexAttrib4NusvPtr  = NULL;
00059 glVertexAttrib4bvProc glVertexAttrib4bvPtr  = NULL;
00060 glVertexAttrib4dProc glVertexAttrib4dPtr  = NULL;
00061 glVertexAttrib4dvProc glVertexAttrib4dvPtr  = NULL;
00062 glVertexAttrib4fProc glVertexAttrib4fPtr  = NULL;
00063 glVertexAttrib4fvProc glVertexAttrib4fvPtr  = NULL;
00064 glVertexAttrib4ivProc glVertexAttrib4ivPtr  = NULL;
00065 glVertexAttrib4sProc glVertexAttrib4sPtr  = NULL;
00066 glVertexAttrib4svProc glVertexAttrib4svPtr  = NULL;
00067 glVertexAttrib4ubvProc glVertexAttrib4ubvPtr  = NULL;
00068 glVertexAttrib4uivProc glVertexAttrib4uivPtr  = NULL;
00069 glVertexAttrib4usvProc glVertexAttrib4usvPtr  = NULL;
00070 glVertexAttribPointerProc glVertexAttribPointerPtr  = NULL;
00071 glEnableVertexAttribArrayProc glEnableVertexAttribArrayPtr  = NULL;
00072 glDisableVertexAttribArrayProc glDisableVertexAttribArrayPtr  = NULL;
00073 glProgramStringProc glProgramStringPtr  = NULL;
00074 glBindProgramProc glBindProgramPtr  = NULL;
00075 glDeleteProgramsProc glDeleteProgramsPtr  = NULL;
00076 glGenProgramsProc glGenProgramsPtr  = NULL;
00077 glProgramEnvParameter4dProc glProgramEnvParameter4dPtr  = NULL;
00078 glProgramEnvParameter4dvProc glProgramEnvParameter4dvPtr  = NULL;
00079 glProgramEnvParameter4fProc glProgramEnvParameter4fPtr  = NULL;
00080 glProgramEnvParameter4fvProc glProgramEnvParameter4fvPtr  = NULL;
00081 glProgramLocalParameter4dProc glProgramLocalParameter4dPtr  = NULL;
00082 glProgramLocalParameter4dvProc glProgramLocalParameter4dvPtr  = NULL;
00083 glProgramLocalParameter4fProc glProgramLocalParameter4fPtr  = NULL;
00084 glProgramLocalParameter4fvProc glProgramLocalParameter4fvPtr  = NULL;
00085 glGetProgramEnvParameterdvProc glGetProgramEnvParameterdvPtr  = NULL;
00086 glGetProgramEnvParameterfvProc glGetProgramEnvParameterfvPtr  = NULL;
00087 glGetProgramLocalParameterdvProc glGetProgramLocalParameterdvPtr  = NULL;
00088 glGetProgramLocalParameterfvProc glGetProgramLocalParameterfvPtr  = NULL;
00089 glGetProgramivProc glGetProgramivPtr  = NULL;
00090 glGetProgramStringProc glGetProgramStringPtr  = NULL;
00091 glGetVertexAttribdvProc glGetVertexAttribdvPtr  = NULL;
00092 glGetVertexAttribfvProc glGetVertexAttribfvPtr  = NULL;
00093 glGetVertexAttribivProc glGetVertexAttribivPtr  = NULL;
00094 glGetVertexAttribPointervProc glGetVertexAttribPointervPtr  = NULL;
00095 glIsProgramProc glIsProgramPtr  = NULL;
00096 
00097 glDeleteObjectProc glDeleteObjectPtr = NULL;
00098 glGetHandleProc glGetHandlePtr = NULL;
00099 glDetachObjectProc glDetachObjectPtr = NULL;
00100 glCreateShaderObjectProc glCreateShaderObjectPtr = NULL;
00101 glShaderSourceProc glShaderSourcePtr = NULL;
00102 glCompileShaderProc glCompileShaderPtr = NULL;
00103 glCreateProgramObjectProc glCreateProgramObjectPtr = NULL;
00104 glAttachObjectProc glAttachObjectPtr = NULL;
00105 glLinkProgramProc glLinkProgramPtr = NULL;
00106 glUseProgramObjectProc glUseProgramObjectPtr = NULL;
00107 glValidateProgramProc glValidateProgramPtr = NULL;
00108 glUniform1fProc glUniform1fPtr = NULL;
00109 glUniform2fProc glUniform2fPtr = NULL;
00110 glUniform3fProc glUniform3fPtr = NULL;
00111 glUniform4fProc glUniform4fPtr = NULL;
00112 glUniform1iProc glUniform1iPtr = NULL;
00113 glUniform2iProc glUniform2iPtr = NULL;
00114 glUniform3iProc glUniform3iPtr = NULL;
00115 glUniform4iProc glUniform4iPtr = NULL;
00116 glUniform1fvProc glUniform1fvPtr = NULL;
00117 glUniform2fvProc glUniform2fvPtr = NULL;
00118 glUniform3fvProc glUniform3fvPtr = NULL;
00119 glUniform4fvProc glUniform4fvPtr = NULL;
00120 glUniform1ivProc glUniform1ivPtr = NULL;
00121 glUniform2ivProc glUniform2ivPtr = NULL;
00122 glUniform3ivProc glUniform3ivPtr = NULL;
00123 glUniform4ivProc glUniform4ivPtr = NULL;
00124 glUniformMatrix2fvProc glUniformMatrix2fvPtr = NULL;
00125 glUniformMatrix3fvProc glUniformMatrix3fvPtr = NULL;
00126 glUniformMatrix4fvProc glUniformMatrix4fvPtr = NULL;
00127 glGetObjectParameterfvProc glGetObjectParameterfvPtr = NULL;
00128 glGetObjectParameterivProc glGetObjectParameterivPtr = NULL;
00129 glGetInfoLogProc glGetInfoLogPtr = NULL;
00130 glGetAttachedObjectsProc glGetAttachedObjectsPtr = NULL;
00131 glGetUniformLocationProc glGetUniformLocationPtr = NULL;
00132 glGetActiveUniformProc glGetActiveUniformPtr = NULL;
00133 glGetUniformfvProc glGetUniformfvPtr = NULL;
00134 glGetUniformivProc glGetUniformivPtr = NULL;
00135 glGetShaderSourceProc glGetShaderSourcePtr = NULL;
00136 
00137 glBindAttribLocationProc glBindAttribLocationPtr = NULL;
00138 glGetActiveAttribProc glGetActiveAttribPtr = NULL;
00139 glGetAttribLocationProc glGetAttribLocationPtr = NULL;
00140 
00141 glBindProgramNVProc glBindProgramNVPtr = NULL;
00142 glDeleteProgramsNVProc glDeleteProgramsNVPtr = NULL;
00143 glGenProgramsNVProc glGenProgramsNVPtr = NULL;
00144 glLoadProgramNVProc glLoadProgramNVPtr = NULL;
00145 glProgramParameter4fvNVProc glProgramParameter4fvNVPtr = NULL;
00146 
00147 bool Shader::VP_supported = false;
00148 bool Shader::FP_supported = false;
00149 bool Shader::GLSL_supported = false;
00150 bool Shader::NVFP_supported = false;
00151 GLint Shader::nb_texture_unit = 0;
00152 
00153 Shader::Shader(const char *name,const char *vertex,const char *fragment) {
00154         
00155         program = 0;
00156         vertex_target = 0;
00157         vertex_id = 0;
00158         fragment_target = 0;
00159         fragment_id = 0;
00160         
00161         char *data;
00162         FILE *file = fopen(name,"rb");
00163         if(!file) {
00164         SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): can't open '" << name << "' file\n");
00165                 return;
00166         }
00167         
00168         fseek(file,0,SEEK_END);
00169         int size = ftell(file);
00170         data = new char[size + 1];
00171         data[size] = '\0';
00172         fseek(file,0,SEEK_SET);
00173         fread(data,1,size,file);
00174         fclose(file);
00175         
00176         // skip comments
00177         char *s = data;
00178         char *d = data;
00179         while(*s) {
00180                 if(*s == '/' && *(s + 1) == '/') {
00181                         while(*s && *s != '\n') s++;
00182                         while(*s && *s == '\n') s++;
00183                         *d++ = '\n';
00184                 }
00185                 else if(*s == '/' && *(s + 1) == '*') {
00186                         while(*s && (*s != '*' || *(s + 1) != '/')) s++;
00187                         s += 2;
00188                         while(*s && *s == '\n') s++;
00189                         *d++ = '\n';
00190                 }
00191                 else *d++ = *s++;
00192         }
00193         *d = '\0';
00194         
00195         // find shaders
00196         char *vertex_src = NULL;
00197         char *fragment_src = NULL;
00198         s = data;
00199         while(*s) {
00200                 if(*s == '<') {
00201                         char *name = s;
00202                         while(*s) {
00203                                 if(strchr("> \t\n\r",*s)) break;
00204                                 s++;
00205                         }
00206                         if(*s == '>') {         // it`s shader
00207                                 *name++ = '\0';
00208                                 *s++ = '\0';
00209                                 while(*s && strchr(" \t\n\r",*s)) s++;
00210                                 if(vertex == NULL && !strcmp(name,"vertex")) vertex_src = s;
00211                                 if(vertex && !strcmp(name,vertex)) vertex_src = s;
00212                                 if(fragment == NULL && !strcmp(name,"fragment")) fragment_src = s;
00213                                 if(fragment && !strcmp(name,fragment)) fragment_src = s;
00214                         }
00215                 }
00216                 s++;
00217         }
00218         
00219         if(vertex_src) {
00220                 
00221                 // ARB vertex program
00222                 if(VP_supported && !strncmp(vertex_src,"!!ARBvp1.0",10)) {
00223                         vertex_target = GL_VERTEX_PROGRAM_ARB;
00224                         glGenProgramsPtr(1,&vertex_id);
00225                         glBindProgramPtr(GL_VERTEX_PROGRAM_ARB,vertex_id);
00226                         glProgramStringPtr(GL_VERTEX_PROGRAM_ARB,GL_PROGRAM_FORMAT_ASCII_ARB,(GLsizei)strlen(vertex_src),vertex_src);
00227                         GLint pos = -1;
00228                         glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB,&pos);
00229                         if(pos != -1) {
00230                                 SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): vertex program error in " << name << " file\n" << get_error(vertex_src,pos));
00231                                 return;
00232                         }
00233                         char *var = strstr(vertex_src, "#var ");
00234                         while( var ) {
00235                                 char *eol = strchr( var + 1, '#');
00236                                 char *c2, *c3, *c4;
00237                                 c2 = strchr( var + 6, ' ');
00238                                 if( c2 ) {
00239                                         c3 = strchr( c2 + 1, ':');
00240                                         if( c3 ) {
00241                                                 c4 = strchr( c3 + 1, ':');
00242                                                 if( c4 )
00243                                                         c4 = strchr( c4 + 1, '[');
00244                                                 if( c4 && c4 < eol) {
00245                                                         char type[10], name[30];
00246                                                         strncpy( type, var + 5, c2-var-5 );
00247                                                         type[c2-var-5] = 0;
00248                                                         strncpy( name, c2 + 1, c3-c2-2 );
00249                                                         name[c3-c2-2] = 0;
00250                                                         struct Parameter p;
00251                                                         p.location = atoi( c4 + 1);
00252                                                         p.length = 4;
00253                                                         if( ! strcmp(type, "float3") )
00254                                                                 p.length = 3;
00255                                                         else if( ! strcmp(type, "float") )
00256                                                                 p.length = 1;
00257                                                         arb_parameters[ name ] = p;
00258                                                 }
00259                                         }
00260                                 }
00261                                 var = strstr(var + 1, "#var ");
00262                         }
00263                 }
00264                 // ARB vertex shader
00265                 else {
00266                 
00267                         program = glCreateProgramObjectPtr();
00268                         
00269                         GLint length = (GLint)strlen(vertex_src);
00270                         GLhandleARB vertex = glCreateShaderObjectPtr(GL_VERTEX_SHADER_ARB);
00271                         glShaderSourcePtr(vertex,1,(const GLcharARB**)&vertex_src,&length);
00272                         glCompileShaderPtr(vertex);
00273                         glAttachObjectPtr(program,vertex);
00274                         glDeleteObjectPtr(vertex);
00275                         
00276                         glBindAttribLocationPtr(program,0,"s_attribute_0");
00277                         glBindAttribLocationPtr(program,1,"s_attribute_1");
00278                         glBindAttribLocationPtr(program,2,"s_attribute_2");
00279                         glBindAttribLocationPtr(program,3,"s_attribute_3");
00280                         glBindAttribLocationPtr(program,4,"s_attribute_4");
00281                         glBindAttribLocationPtr(program,5,"s_attribute_5");
00282                         glBindAttribLocationPtr(program,6,"s_attribute_6");
00283                         
00284                         glBindAttribLocationPtr(program,0,"s_xyz");
00285                         glBindAttribLocationPtr(program,1,"s_normal");
00286                         glBindAttribLocationPtr(program,2,"s_tangent");
00287                         glBindAttribLocationPtr(program,3,"s_binormal");
00288                         glBindAttribLocationPtr(program,4,"s_texcoord");
00289                 }
00290         }
00291         
00292         if(fragment_src) {
00293                 
00294                 // ARB fragment program
00295                 if(FP_supported && !strncmp(fragment_src,"!!ARBfp1.0",10)) {
00296                         fragment_target = GL_FRAGMENT_PROGRAM_ARB;
00297                         glGenProgramsPtr(1,&fragment_id);
00298                         glBindProgramPtr(GL_FRAGMENT_PROGRAM_ARB,fragment_id);
00299                         glProgramStringPtr(GL_FRAGMENT_PROGRAM_ARB,GL_PROGRAM_FORMAT_ASCII_ARB,(GLsizei)strlen(fragment_src),fragment_src);
00300                         GLint pos = -1;
00301                         glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB,&pos);
00302                         if(pos != -1) {
00303                                 SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): fragment program error in " << name << " file\n" << get_error(fragment_src,pos));
00304                                 return;
00305                         }
00306                 }
00307 
00308                 // NV fragment program
00309                 else if(!strncmp(fragment_src,"!!FP1.0",7)) {
00310                         fragment_target = GL_FRAGMENT_PROGRAM_NV;
00311                         glGenProgramsNVPtr(1,&fragment_id);
00312                         glBindProgramNVPtr(GL_FRAGMENT_PROGRAM_NV,fragment_id);
00313                         glLoadProgramNVPtr(GL_FRAGMENT_PROGRAM_NV,fragment_id,(GLsizei)strlen(fragment_src),(GLubyte*)fragment_src);
00314                         GLint pos = -1;
00315                         glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV,&pos);
00316                         if(pos != -1) {
00317                                 SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): fragment program error in " << name << " file\n" << get_error(fragment_src,pos));
00318                                 return;
00319                         }
00320                 }
00321                 
00322                 // ARB fragment shader
00323                 else {
00324                         
00325                         if(!program) program = glCreateProgramObjectPtr();
00326                         
00327                         GLint length = (GLint)strlen(fragment_src);
00328                         GLhandleARB fragment = glCreateShaderObjectPtr(GL_FRAGMENT_SHADER_ARB);
00329                         glShaderSourcePtr(fragment,1,(const GLcharARB**)&fragment_src,&length);
00330                         glCompileShaderPtr(fragment);
00331                         glAttachObjectPtr(program,fragment);
00332                         glDeleteObjectPtr(fragment);
00333                 }
00334         }
00335         
00336         if(program) {
00337 
00338                 glLinkProgramPtr(program);
00339                 GLint linked;
00340                 glGetObjectParameterivPtr(program,GL_OBJECT_LINK_STATUS_ARB,&linked);
00341                 if(!linked) {
00342                         SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): GLSL error in " << name << " file\n" << get_glsl_error());
00343                         return;
00344                 }
00345                 
00346                 glUseProgramObjectPtr(program);
00347                 
00348                 for(int i = 0; i < 8; i++) {
00349                         char texture[32];
00350                         snprintf(texture, 32, "s_texture_%d",i);
00351                         GLint location = glGetUniformLocationPtr(program,texture);
00352                         if(location >= 0) glUniform1iPtr(location,i);
00353                 }
00354                 
00355                 glUseProgramObjectPtr(0);
00356                 
00357                 glValidateProgramPtr(program);
00358                 GLint validated;
00359                 glGetObjectParameterivPtr(program,GL_OBJECT_VALIDATE_STATUS_ARB,&validated);
00360                 if(!validated) {
00361                         SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): GLSL error in " << name << " file\n" << get_glsl_error());
00362                         return;
00363                 }
00364         }
00365         
00366         delete [] data;
00367 }
00368 
00369 Shader::~Shader() {
00370         if(program) glDeleteObjectPtr(program);
00371         if(vertex_target == GL_VERTEX_PROGRAM_ARB) glDeleteProgramsPtr(1,&vertex_id);
00372         if(fragment_target == GL_FRAGMENT_PROGRAM_ARB) glDeleteProgramsPtr(1,&fragment_id);
00373         else if(fragment_target == GL_FRAGMENT_PROGRAM_NV) glDeleteProgramsNVPtr(1,&fragment_id);
00374         parameters.clear();
00375 }
00376 
00377 /*
00378  */
00379 const char *Shader::get_error(char *data,int pos) {
00380         char *s = data;
00381         while(*s && pos--) s++;
00382         while(s >= data && *s != '\n') s--;
00383         char *e = ++s;
00384         while(*e != '\0' && *e != '\n') e++;
00385         *e = '\0';
00386         return s;
00387 }
00388 
00389 /*
00390  */
00391 
00392 const char *Shader::get_glsl_error() {
00393         GLint length;
00394         static char error[4096];
00395         glGetInfoLogPtr(program,sizeof(error),&length,error);
00396         return error;
00397 }
00398 
00399 /*
00400  */
00401 void Shader::getParameter(const char *name,Parameter *parameter) {
00402         if( program ) {
00403                 char buf[1024];
00404                 strcpy(buf,name);
00405                 char *s = strchr(buf,':');
00406                 if(s) {
00407                         *s++ = '\0';
00408                         parameter->length = atoi(s);
00409                 } else {
00410                         parameter->length = 4;
00411                 }
00412                 parameter->location = glGetUniformLocationPtr(program,buf);
00413         } else if( vertex_id ) {
00414                 arb_parameter_list::iterator iParam = arb_parameters.find(name);
00415                 if( iParam != arb_parameters.end() )
00416                         parameter->location = iParam->second.location;
00417                 else
00418                         parameter->location = 90;
00419                 parameter->length = 4;
00420         }
00421 }
00422 
00423 /*
00424  */
00425 void Shader::bindNames(const char *name,...) {
00426         Parameter parameter;
00427         getParameter(name,&parameter);
00428         parameters.push_back(parameter);
00429         va_list args;
00430         va_start(args,name);
00431         while(1) {
00432                 const char *name = va_arg(args,const char*);
00433                 if(name == NULL) break;
00434                 getParameter(name,&parameter);
00435                 parameters.push_back(parameter);
00436         }
00437         va_end(args);
00438 }
00439 
00440 /*****************************************************************************/
00441 /*                                                                           */
00442 /* enable/disable/bind                                                       */
00443 /*                                                                           */
00444 /*****************************************************************************/
00445 
00446 /*
00447  */
00448 void Shader::enable() {
00449         if(vertex_id) glEnable(vertex_target);
00450         if(fragment_id) glEnable(fragment_target);
00451 }
00452 
00453 /*
00454  */
00455 void Shader::disable() {
00456         if(program) glUseProgramObjectPtr(0);
00457         if(vertex_id) glDisable(vertex_target);
00458         if(fragment_id) glDisable(fragment_target);
00459 }
00460 
00461 /*
00462  */
00463 void Shader::bind() {
00464         if(program) glUseProgramObjectPtr(program);
00465         if(vertex_id) {
00466                 if(vertex_target == GL_VERTEX_PROGRAM_ARB) glBindProgramPtr(vertex_target,vertex_id);
00467         }
00468         if(fragment_id) {
00469                 if(fragment_target == GL_FRAGMENT_PROGRAM_ARB) glBindProgramPtr(fragment_target,fragment_id);
00470                 else if(fragment_target == GL_FRAGMENT_PROGRAM_NV) glBindProgramNVPtr(fragment_target,fragment_id);
00471         }
00472 }
00473 
00474 /*
00475  */
00476 void Shader::bind(const float *v,...) {
00477         if(fragment_id) {
00478                 if(fragment_target == GL_FRAGMENT_PROGRAM_ARB) glBindProgramPtr(fragment_target,fragment_id);
00479                 else if(fragment_target == GL_FRAGMENT_PROGRAM_NV) glBindProgramNVPtr(fragment_target,fragment_id);
00480     } else {
00481             if(program == 0) {
00482                     SG_LOG(SG_GL, SG_ALERT, "Shader::bind(): error GLSL shader isn't loaded\n");
00483                     return;
00484             }
00485             glUseProgramObjectPtr(program);
00486     }
00487         const float *value = v;
00488         va_list args;
00489         va_start(args,v);
00490         for(int i = 0; i < (int)parameters.size(); i++) {
00491                 if( vertex_target ) {
00492                         glProgramLocalParameter4fvPtr( vertex_target, parameters[i].location, value);
00493                 } else if( program ) {
00494                         if(parameters[i].length == 1) glUniform1fvPtr(parameters[i].location,1,value);
00495                         else if(parameters[i].length == 2) glUniform2fvPtr(parameters[i].location,1,value);
00496                         else if(parameters[i].length == 3) glUniform3fvPtr(parameters[i].location,1,value);
00497                         else if(parameters[i].length == 4) glUniform4fvPtr(parameters[i].location,1,value);
00498                         else if(parameters[i].length == 9) glUniformMatrix3fvPtr(parameters[i].location,1,false,value);
00499                         else if(parameters[i].length == 16) glUniformMatrix4fvPtr(parameters[i].location,1,false,value);
00500                 }
00501                 value = va_arg(args,const float*);
00502                 if(!value) break;
00503         }
00504         va_end(args);
00505 }
00506 
00507 /*****************************************************************************/
00508 /*                                                                           */
00509 /* set parameters                                                            */
00510 /*                                                                           */
00511 /*****************************************************************************/
00512 
00513 void Shader::setLocalParameter(int location,const float *value) {
00514         if(vertex_target == 0) {
00515                 SG_LOG(SG_GL, SG_ALERT, "Shader::setLocalParameter(): error vertex program isn't loaded\n");
00516                 return;
00517         }
00518         glProgramLocalParameter4fvPtr(vertex_target,location,value);
00519 }
00520 
00521 void Shader::setEnvParameter(int location,const float *value) {
00522         if(vertex_target == 0) {
00523                 SG_LOG(SG_GL, SG_ALERT, "Shader::setEnvParameter(): error vertex program isn't loaded\n");
00524                 return;
00525         }
00526         glProgramEnvParameter4fvPtr(vertex_target,location,value);
00527 }
00528 
00529 /*
00530  */
00531 void Shader::setParameter(const char *name,const float *value) {
00532         Parameter parameter;
00533         getParameter(name,&parameter);
00534         if( vertex_target ) {
00535                 glProgramLocalParameter4fvPtr( vertex_target, parameter.location, value);
00536                 return;
00537         }
00538         if(program == 0) {
00539                 SG_LOG(SG_GL, SG_ALERT, "Shader::setLocalParameter(): error GLSL shader isn't loaded\n");
00540                 return;
00541         }
00542         if(parameter.length == 1) glUniform1fvPtr(parameter.location,1,value);
00543         else if(parameter.length == 2) glUniform2fvPtr(parameter.location,1,value);
00544         else if(parameter.length == 3) glUniform3fvPtr(parameter.location,1,value);
00545         else if(parameter.length == 4) glUniform4fvPtr(parameter.location,1,value);
00546         else if(parameter.length == 9) glUniformMatrix3fvPtr(parameter.location,1,false,value);
00547         else if(parameter.length == 16) glUniformMatrix4fvPtr(parameter.location,1,false,value);
00548 }
00549 
00550 /*
00551  */
00552 void Shader::setParameters(const float *v,...) {
00553         const float *value = v;
00554         va_list args;
00555         va_start(args,v);
00556         for(int i = 0; i < (int)parameters.size(); i++) {
00557                 if( vertex_target ) {
00558                         glProgramLocalParameter4fvPtr( vertex_target, parameters[i].location, value);
00559                 } else if( program ) {
00560                         if(parameters[i].length == 1) glUniform1fvPtr(parameters[i].location,1,value);
00561                         else if(parameters[i].length == 2) glUniform2fvPtr(parameters[i].location,1,value);
00562                         else if(parameters[i].length == 3) glUniform3fvPtr(parameters[i].location,1,value);
00563                         else if(parameters[i].length == 4) glUniform4fvPtr(parameters[i].location,1,value);
00564                         else if(parameters[i].length == 9) glUniformMatrix3fvPtr(parameters[i].location,1,false,value);
00565                         else if(parameters[i].length == 16) glUniformMatrix4fvPtr(parameters[i].location,1,false,value);
00566                 }
00567                 value = va_arg(args,const float*);
00568                 if(!value) break;
00569         }
00570         va_end(args);
00571 }
00572 
00573 #ifndef CONCAT
00574 #define CONCAT(a,b) a##b
00575 #endif
00576 #define mystringify(a) CONCAT(ST,R)(a)
00577 #define STR(x) #x
00578 #define LOAD_EXT(fn) CONCAT(fn,Ptr) = (CONCAT(fn,Proc)) SGLookupFunction( mystringify(CONCAT(fn,ARB)) )
00579 
00580 void Shader::Init(void) {
00581         if( SGIsOpenGLExtensionSupported("GL_ARB_multitexture") )
00582                 glGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, &nb_texture_unit );
00583         VP_supported = SGIsOpenGLExtensionSupported("GL_ARB_vertex_program");
00584         FP_supported = SGIsOpenGLExtensionSupported("GL_ARB_fragment_program");
00585         // check that
00586         GLSL_supported = SGIsOpenGLExtensionSupported("GL_ARB_shading_language_100") &&
00587                 SGIsOpenGLExtensionSupported("GL_ARB_fragment_shader") &&
00588                 SGIsOpenGLExtensionSupported("GL_ARB_vertex_shader") &&
00589                 SGIsOpenGLExtensionSupported("GL_ARB_shader_objects");
00590     NVFP_supported = SGIsOpenGLExtensionSupported("GL_NV_fragment_program");
00591 
00592         if( VP_supported || FP_supported ) {
00593                 /* All ARB_fragment_program entry points are shared with ARB_vertex_program. */
00594         LOAD_EXT(glVertexAttrib1d);
00595         LOAD_EXT( glVertexAttrib1dv );
00596         LOAD_EXT( glVertexAttrib1f );
00597         LOAD_EXT( glVertexAttrib1fv );
00598         LOAD_EXT( glVertexAttrib1s );
00599         LOAD_EXT( glVertexAttrib1sv );
00600         LOAD_EXT( glVertexAttrib2d );
00601         LOAD_EXT( glVertexAttrib2dv );
00602         LOAD_EXT( glVertexAttrib2f );
00603         LOAD_EXT( glVertexAttrib2fv );
00604         LOAD_EXT( glVertexAttrib2s );
00605         LOAD_EXT( glVertexAttrib2sv );
00606         LOAD_EXT( glVertexAttrib3d );
00607         LOAD_EXT( glVertexAttrib3dv );
00608         LOAD_EXT( glVertexAttrib3f );
00609         LOAD_EXT( glVertexAttrib3fv );
00610         LOAD_EXT( glVertexAttrib3s );
00611         LOAD_EXT( glVertexAttrib3sv );
00612         LOAD_EXT( glVertexAttrib4Nbv );
00613         LOAD_EXT( glVertexAttrib4Niv );
00614         LOAD_EXT( glVertexAttrib4Nsv );
00615         LOAD_EXT( glVertexAttrib4Nub );
00616         LOAD_EXT( glVertexAttrib4Nubv );
00617         LOAD_EXT( glVertexAttrib4Nuiv );
00618         LOAD_EXT( glVertexAttrib4Nusv );
00619         LOAD_EXT( glVertexAttrib4bv );
00620         LOAD_EXT( glVertexAttrib4d );
00621         LOAD_EXT( glVertexAttrib4dv );
00622         LOAD_EXT( glVertexAttrib4f );
00623         LOAD_EXT( glVertexAttrib4fv );
00624         LOAD_EXT( glVertexAttrib4iv );
00625         LOAD_EXT( glVertexAttrib4s );
00626         LOAD_EXT( glVertexAttrib4sv );
00627         LOAD_EXT( glVertexAttrib4ubv );
00628         LOAD_EXT( glVertexAttrib4uiv );
00629         LOAD_EXT( glVertexAttrib4usv );
00630         LOAD_EXT( glVertexAttribPointer );
00631         LOAD_EXT( glEnableVertexAttribArray );
00632         LOAD_EXT( glDisableVertexAttribArray );
00633         LOAD_EXT( glProgramString );
00634         LOAD_EXT( glBindProgram );
00635         LOAD_EXT( glDeletePrograms );
00636         LOAD_EXT( glGenPrograms );
00637         LOAD_EXT( glProgramEnvParameter4d );
00638         LOAD_EXT( glProgramEnvParameter4dv );
00639         LOAD_EXT( glProgramEnvParameter4f );
00640         LOAD_EXT( glProgramEnvParameter4fv );
00641         LOAD_EXT( glProgramLocalParameter4d );
00642         LOAD_EXT( glProgramLocalParameter4dv );
00643         LOAD_EXT( glProgramLocalParameter4f );
00644         LOAD_EXT( glProgramLocalParameter4fv );
00645         LOAD_EXT( glGetProgramEnvParameterdv );
00646         LOAD_EXT( glGetProgramEnvParameterfv );
00647         LOAD_EXT( glGetProgramLocalParameterdv );
00648         LOAD_EXT( glGetProgramLocalParameterfv );
00649         LOAD_EXT( glGetProgramiv );
00650         LOAD_EXT( glGetProgramString );
00651         LOAD_EXT( glGetVertexAttribdv );
00652         LOAD_EXT( glGetVertexAttribfv );
00653         LOAD_EXT( glGetVertexAttribiv );
00654         LOAD_EXT( glGetVertexAttribPointerv );
00655         LOAD_EXT( glIsProgram );
00656         }
00657         if( GLSL_supported ) {
00658         LOAD_EXT( glDeleteObject );
00659         LOAD_EXT( glGetHandle );
00660         LOAD_EXT( glDetachObject );
00661         LOAD_EXT( glCreateShaderObject );
00662         LOAD_EXT( glShaderSource );
00663         LOAD_EXT( glCompileShader );
00664         LOAD_EXT( glCreateProgramObject );
00665         LOAD_EXT( glAttachObject );
00666         LOAD_EXT( glLinkProgram );
00667         LOAD_EXT( glUseProgramObject );
00668         LOAD_EXT( glValidateProgram );
00669         LOAD_EXT( glUniform1f );
00670         LOAD_EXT( glUniform2f );
00671         LOAD_EXT( glUniform3f );
00672         LOAD_EXT( glUniform4f );
00673         LOAD_EXT( glUniform1i );
00674         LOAD_EXT( glUniform2i );
00675         LOAD_EXT( glUniform3i );
00676         LOAD_EXT( glUniform4i );
00677         LOAD_EXT( glUniform1fv );
00678         LOAD_EXT( glUniform2fv );
00679         LOAD_EXT( glUniform3fv );
00680         LOAD_EXT( glUniform4fv );
00681         LOAD_EXT( glUniform1iv );
00682         LOAD_EXT( glUniform2iv );
00683         LOAD_EXT( glUniform3iv );
00684         LOAD_EXT( glUniform4iv );
00685         LOAD_EXT( glUniformMatrix2fv );
00686         LOAD_EXT( glUniformMatrix3fv );
00687         LOAD_EXT( glUniformMatrix4fv );
00688         LOAD_EXT( glGetObjectParameterfv );
00689         LOAD_EXT( glGetObjectParameteriv );
00690         LOAD_EXT( glGetInfoLog );
00691         LOAD_EXT( glGetAttachedObjects );
00692         LOAD_EXT( glGetUniformLocation );
00693         LOAD_EXT( glGetActiveUniform );
00694         LOAD_EXT( glGetUniformfv );
00695         LOAD_EXT( glGetUniformiv );
00696         LOAD_EXT( glGetShaderSource );
00697 
00698         LOAD_EXT( glBindAttribLocation );
00699         LOAD_EXT( glGetActiveAttrib );
00700         LOAD_EXT( glGetAttribLocation );
00701 
00702         }
00703     if( NVFP_supported ) {
00704         glBindProgramNVPtr = (glBindProgramNVProc) SGLookupFunction( "glBindProgramNV" );
00705         glDeleteProgramsNVPtr = (glDeleteProgramsNVProc) SGLookupFunction( "glDeleteProgramsNV" );
00706         glGenProgramsNVPtr = (glGenProgramsNVProc) SGLookupFunction( "glGenProgramsNV" );
00707         glLoadProgramNVPtr = (glLoadProgramNVProc) SGLookupFunction( "glLoadProgramNV" );
00708         glProgramParameter4fvNVPtr = (glProgramParameter4fvNVProc) SGLookupFunction( "glProgramParameter4fvNV" );
00709     }
00710 }

Generated on Mon Dec 17 09:30:55 2007 for SimGear by  doxygen 1.5.1