]> git.mxchange.org Git - simgear.git/blob - simgear/screen/shader.cpp
Mac OS X fixes from Markus Morawitz
[simgear.git] / simgear / screen / shader.cpp
1 /* Shader
2  *
3  * Copyright (C) 2003-2005, Alexander Zaprjagaev <frustum@frustum.org>
4  *                          Roman Grigoriev <grigoriev@gosniias.ru>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21
22 #include <simgear/debug/logstream.hxx>
23 #include "shader.h"
24 #include <stdio.h>
25 #include <stdarg.h>
26
27
28 glVertexAttrib1dProc glVertexAttrib1dPtr = NULL;
29 glVertexAttrib1dvProc glVertexAttrib1dvPtr = NULL;
30 glVertexAttrib1fProc glVertexAttrib1fPtr = NULL;
31 glVertexAttrib1fvProc glVertexAttrib1fvPtr = NULL;
32 glVertexAttrib1sProc glVertexAttrib1sPtr  = NULL;
33 glVertexAttrib1svProc glVertexAttrib1svPtr  = NULL;
34 glVertexAttrib2dProc glVertexAttrib2dPtr  = NULL;
35 glVertexAttrib2dvProc glVertexAttrib2dvPtr  = NULL;
36 glVertexAttrib2fProc glVertexAttrib2fPtr  = NULL;
37 glVertexAttrib2fvProc glVertexAttrib2fvPtr  = NULL;
38 glVertexAttrib2sProc glVertexAttrib2sPtr  = NULL;
39 glVertexAttrib2svProc glVertexAttrib2svPtr  = NULL;
40 glVertexAttrib3dProc glVertexAttrib3dPtr  = NULL;
41 glVertexAttrib3dvProc glVertexAttrib3dvPtr  = NULL;
42 glVertexAttrib3fProc glVertexAttrib3fPtr  = NULL;
43 glVertexAttrib3fvProc glVertexAttrib3fvPtr  = NULL;
44 glVertexAttrib3sProc glVertexAttrib3sPtr  = NULL;
45 glVertexAttrib3svProc glVertexAttrib3svPtr  = NULL;
46 glVertexAttrib4NbvProc glVertexAttrib4NbvPtr  = NULL;
47 glVertexAttrib4NivProc glVertexAttrib4NivPtr  = NULL;
48 glVertexAttrib4NsvProc glVertexAttrib4NsvPtr  = NULL;
49 glVertexAttrib4NubProc glVertexAttrib4NubPtr  = NULL;
50 glVertexAttrib4NubvProc glVertexAttrib4NubvPtr  = NULL;
51 glVertexAttrib4NuivProc glVertexAttrib4NuivPtr  = NULL;
52 glVertexAttrib4NusvProc glVertexAttrib4NusvPtr  = NULL;
53 glVertexAttrib4bvProc glVertexAttrib4bvPtr  = NULL;
54 glVertexAttrib4dProc glVertexAttrib4dPtr  = NULL;
55 glVertexAttrib4dvProc glVertexAttrib4dvPtr  = NULL;
56 glVertexAttrib4fProc glVertexAttrib4fPtr  = NULL;
57 glVertexAttrib4fvProc glVertexAttrib4fvPtr  = NULL;
58 glVertexAttrib4ivProc glVertexAttrib4ivPtr  = NULL;
59 glVertexAttrib4sProc glVertexAttrib4sPtr  = NULL;
60 glVertexAttrib4svProc glVertexAttrib4svPtr  = NULL;
61 glVertexAttrib4ubvProc glVertexAttrib4ubvPtr  = NULL;
62 glVertexAttrib4uivProc glVertexAttrib4uivPtr  = NULL;
63 glVertexAttrib4usvProc glVertexAttrib4usvPtr  = NULL;
64 glVertexAttribPointerProc glVertexAttribPointerPtr  = NULL;
65 glEnableVertexAttribArrayProc glEnableVertexAttribArrayPtr  = NULL;
66 glDisableVertexAttribArrayProc glDisableVertexAttribArrayPtr  = NULL;
67 glProgramStringProc glProgramStringPtr  = NULL;
68 glBindProgramProc glBindProgramPtr  = NULL;
69 glDeleteProgramsProc glDeleteProgramsPtr  = NULL;
70 glGenProgramsProc glGenProgramsPtr  = NULL;
71 glProgramEnvParameter4dProc glProgramEnvParameter4dPtr  = NULL;
72 glProgramEnvParameter4dvProc glProgramEnvParameter4dvPtr  = NULL;
73 glProgramEnvParameter4fProc glProgramEnvParameter4fPtr  = NULL;
74 glProgramEnvParameter4fvProc glProgramEnvParameter4fvPtr  = NULL;
75 glProgramLocalParameter4dProc glProgramLocalParameter4dPtr  = NULL;
76 glProgramLocalParameter4dvProc glProgramLocalParameter4dvPtr  = NULL;
77 glProgramLocalParameter4fProc glProgramLocalParameter4fPtr  = NULL;
78 glProgramLocalParameter4fvProc glProgramLocalParameter4fvPtr  = NULL;
79 glGetProgramEnvParameterdvProc glGetProgramEnvParameterdvPtr  = NULL;
80 glGetProgramEnvParameterfvProc glGetProgramEnvParameterfvPtr  = NULL;
81 glGetProgramLocalParameterdvProc glGetProgramLocalParameterdvPtr  = NULL;
82 glGetProgramLocalParameterfvProc glGetProgramLocalParameterfvPtr  = NULL;
83 glGetProgramivProc glGetProgramivPtr  = NULL;
84 glGetProgramStringProc glGetProgramStringPtr  = NULL;
85 glGetVertexAttribdvProc glGetVertexAttribdvPtr  = NULL;
86 glGetVertexAttribfvProc glGetVertexAttribfvPtr  = NULL;
87 glGetVertexAttribivProc glGetVertexAttribivPtr  = NULL;
88 glGetVertexAttribPointervProc glGetVertexAttribPointervPtr  = NULL;
89 glIsProgramProc glIsProgramPtr  = NULL;
90
91 glDeleteObjectProc glDeleteObjectPtr = NULL;
92 glGetHandleProc glGetHandlePtr = NULL;
93 glDetachObjectProc glDetachObjectPtr = NULL;
94 glCreateShaderObjectProc glCreateShaderObjectPtr = NULL;
95 glShaderSourceProc glShaderSourcePtr = NULL;
96 glCompileShaderProc glCompileShaderPtr = NULL;
97 glCreateProgramObjectProc glCreateProgramObjectPtr = NULL;
98 glAttachObjectProc glAttachObjectPtr = NULL;
99 glLinkProgramProc glLinkProgramPtr = NULL;
100 glUseProgramObjectProc glUseProgramObjectPtr = NULL;
101 glValidateProgramProc glValidateProgramPtr = NULL;
102 glUniform1fProc glUniform1fPtr = NULL;
103 glUniform2fProc glUniform2fPtr = NULL;
104 glUniform3fProc glUniform3fPtr = NULL;
105 glUniform4fProc glUniform4fPtr = NULL;
106 glUniform1iProc glUniform1iPtr = NULL;
107 glUniform2iProc glUniform2iPtr = NULL;
108 glUniform3iProc glUniform3iPtr = NULL;
109 glUniform4iProc glUniform4iPtr = NULL;
110 glUniform1fvProc glUniform1fvPtr = NULL;
111 glUniform2fvProc glUniform2fvPtr = NULL;
112 glUniform3fvProc glUniform3fvPtr = NULL;
113 glUniform4fvProc glUniform4fvPtr = NULL;
114 glUniform1ivProc glUniform1ivPtr = NULL;
115 glUniform2ivProc glUniform2ivPtr = NULL;
116 glUniform3ivProc glUniform3ivPtr = NULL;
117 glUniform4ivProc glUniform4ivPtr = NULL;
118 glUniformMatrix2fvProc glUniformMatrix2fvPtr = NULL;
119 glUniformMatrix3fvProc glUniformMatrix3fvPtr = NULL;
120 glUniformMatrix4fvProc glUniformMatrix4fvPtr = NULL;
121 glGetObjectParameterfvProc glGetObjectParameterfvPtr = NULL;
122 glGetObjectParameterivProc glGetObjectParameterivPtr = NULL;
123 glGetInfoLogProc glGetInfoLogPtr = NULL;
124 glGetAttachedObjectsProc glGetAttachedObjectsPtr = NULL;
125 glGetUniformLocationProc glGetUniformLocationPtr = NULL;
126 glGetActiveUniformProc glGetActiveUniformPtr = NULL;
127 glGetUniformfvProc glGetUniformfvPtr = NULL;
128 glGetUniformivProc glGetUniformivPtr = NULL;
129 glGetShaderSourceProc glGetShaderSourcePtr = NULL;
130
131 glBindAttribLocationProc glBindAttribLocationPtr = NULL;
132 glGetActiveAttribProc glGetActiveAttribPtr = NULL;
133 glGetAttribLocationProc glGetAttribLocationPtr = NULL;
134
135 glBindProgramNVProc glBindProgramNVPtr = NULL;
136 glDeleteProgramsNVProc glDeleteProgramsNVPtr = NULL;
137 glGenProgramsNVProc glGenProgramsNVPtr = NULL;
138 glLoadProgramNVProc glLoadProgramNVPtr = NULL;
139 glProgramParameter4fvNVProc glProgramParameter4fvNVPtr = NULL;
140
141 bool Shader::VP_supported = false;
142 bool Shader::FP_supported = false;
143 bool Shader::GLSL_supported = false;
144 bool Shader::NVFP_supported = false;
145 GLint Shader::nb_texture_unit = 0;
146
147 Shader::Shader(const char *name,const char *vertex,const char *fragment) {
148         
149         program = 0;
150         vertex_target = 0;
151         vertex_id = 0;
152         fragment_target = 0;
153         fragment_id = 0;
154         
155         char *data;
156         FILE *file = fopen(name,"rb");
157         if(!file) {
158         SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): can't open '" << name << "' file\n");
159                 return;
160         }
161         
162         fseek(file,0,SEEK_END);
163         int size = ftell(file);
164         data = new char[size + 1];
165         data[size] = '\0';
166         fseek(file,0,SEEK_SET);
167         fread(data,1,size,file);
168         fclose(file);
169         
170         // skip comments
171         char *s = data;
172         char *d = data;
173         while(*s) {
174                 if(*s == '/' && *(s + 1) == '/') {
175                         while(*s && *s != '\n') s++;
176                         while(*s && *s == '\n') s++;
177                         *d++ = '\n';
178                 }
179                 else if(*s == '/' && *(s + 1) == '*') {
180                         while(*s && (*s != '*' || *(s + 1) != '/')) s++;
181                         s += 2;
182                         while(*s && *s == '\n') s++;
183                         *d++ = '\n';
184                 }
185                 else *d++ = *s++;
186         }
187         *d = '\0';
188         
189         // find shaders
190         char *vertex_src = NULL;
191         char *fragment_src = NULL;
192         s = data;
193         while(*s) {
194                 if(*s == '<') {
195                         char *name = s;
196                         while(*s) {
197                                 if(strchr("> \t\n\r",*s)) break;
198                                 s++;
199                         }
200                         if(*s == '>') {         // it`s shader
201                                 *name++ = '\0';
202                                 *s++ = '\0';
203                                 while(*s && strchr(" \t\n\r",*s)) s++;
204                                 if(vertex == NULL && !strcmp(name,"vertex")) vertex_src = s;
205                                 if(vertex && !strcmp(name,vertex)) vertex_src = s;
206                                 if(fragment == NULL && !strcmp(name,"fragment")) fragment_src = s;
207                                 if(fragment && !strcmp(name,fragment)) fragment_src = s;
208                         }
209                 }
210                 s++;
211         }
212         
213         if(vertex_src) {
214                 
215                 // ARB vertex program
216                 if(VP_supported && !strncmp(vertex_src,"!!ARBvp1.0",10)) {
217                         vertex_target = GL_VERTEX_PROGRAM_ARB;
218                         glGenProgramsPtr(1,&vertex_id);
219                         glBindProgramPtr(GL_VERTEX_PROGRAM_ARB,vertex_id);
220                         glProgramStringPtr(GL_VERTEX_PROGRAM_ARB,GL_PROGRAM_FORMAT_ASCII_ARB,(GLsizei)strlen(vertex_src),vertex_src);
221                         GLint pos = -1;
222                         glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB,&pos);
223                         if(pos != -1) {
224                                 SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): vertex program error in " << name << " file\n" << get_error(vertex_src,pos));
225                                 return;
226                         }
227                         char *var = strstr(vertex_src, "#var ");
228                         while( var ) {
229                                 char *eol = strchr( var + 1, '#');
230                                 char *c2, *c3, *c4;
231                                 c2 = strchr( var + 6, ' ');
232                                 if( c2 ) {
233                                         c3 = strchr( c2 + 1, ':');
234                                         if( c3 ) {
235                                                 c4 = strchr( c3 + 1, ':');
236                                                 if( c4 )
237                                                         c4 = strchr( c4 + 1, '[');
238                                                 if( c4 && c4 < eol) {
239                                                         char type[10], name[30];
240                                                         strncpy( type, var + 5, c2-var-5 );
241                                                         type[c2-var-5] = 0;
242                                                         strncpy( name, c2 + 1, c3-c2-2 );
243                                                         name[c3-c2-2] = 0;
244                                                         struct Parameter p;
245                                                         p.location = atoi( c4 + 1);
246                                                         p.length = 4;
247                                                         if( ! strcmp(type, "float3") )
248                                                                 p.length = 3;
249                                                         else if( ! strcmp(type, "float") )
250                                                                 p.length = 1;
251                                                         arb_parameters[ name ] = p;
252                                                 }
253                                         }
254                                 }
255                                 var = strstr(var + 1, "#var ");
256                         }
257                 }
258                 // ARB vertex shader
259                 else {
260                 
261                         program = glCreateProgramObjectPtr();
262                         
263                         GLint length = (GLint)strlen(vertex_src);
264                         GLhandleARB vertex = glCreateShaderObjectPtr(GL_VERTEX_SHADER_ARB);
265                         glShaderSourcePtr(vertex,1,(const GLcharARB**)&vertex_src,&length);
266                         glCompileShaderPtr(vertex);
267                         glAttachObjectPtr(program,vertex);
268                         glDeleteObjectPtr(vertex);
269                         
270                         glBindAttribLocationPtr(program,0,"s_attribute_0");
271                         glBindAttribLocationPtr(program,1,"s_attribute_1");
272                         glBindAttribLocationPtr(program,2,"s_attribute_2");
273                         glBindAttribLocationPtr(program,3,"s_attribute_3");
274                         glBindAttribLocationPtr(program,4,"s_attribute_4");
275                         glBindAttribLocationPtr(program,5,"s_attribute_5");
276                         glBindAttribLocationPtr(program,6,"s_attribute_6");
277                         
278                         glBindAttribLocationPtr(program,0,"s_xyz");
279                         glBindAttribLocationPtr(program,1,"s_normal");
280                         glBindAttribLocationPtr(program,2,"s_tangent");
281                         glBindAttribLocationPtr(program,3,"s_binormal");
282                         glBindAttribLocationPtr(program,4,"s_texcoord");
283                 }
284         }
285         
286         if(fragment_src) {
287                 
288                 // ARB fragment program
289                 if(FP_supported && !strncmp(fragment_src,"!!ARBfp1.0",10)) {
290                         fragment_target = GL_FRAGMENT_PROGRAM_ARB;
291                         glGenProgramsPtr(1,&fragment_id);
292                         glBindProgramPtr(GL_FRAGMENT_PROGRAM_ARB,fragment_id);
293                         glProgramStringPtr(GL_FRAGMENT_PROGRAM_ARB,GL_PROGRAM_FORMAT_ASCII_ARB,(GLsizei)strlen(fragment_src),fragment_src);
294                         GLint pos = -1;
295                         glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB,&pos);
296                         if(pos != -1) {
297                                 SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): fragment program error in " << name << " file\n" << get_error(fragment_src,pos));
298                                 return;
299                         }
300                 }
301
302                 // NV fragment program
303                 else if(!strncmp(fragment_src,"!!FP1.0",7)) {
304                         fragment_target = GL_FRAGMENT_PROGRAM_NV;
305                         glGenProgramsNVPtr(1,&fragment_id);
306                         glBindProgramNVPtr(GL_FRAGMENT_PROGRAM_NV,fragment_id);
307                         glLoadProgramNVPtr(GL_FRAGMENT_PROGRAM_NV,fragment_id,(GLsizei)strlen(fragment_src),(GLubyte*)fragment_src);
308                         GLint pos = -1;
309                         glGetIntegerv(GL_PROGRAM_ERROR_POSITION_NV,&pos);
310                         if(pos != -1) {
311                                 SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): fragment program error in " << name << " file\n" << get_error(fragment_src,pos));
312                                 return;
313                         }
314                 }
315                 
316                 // ARB fragment shader
317                 else {
318                         
319                         if(!program) program = glCreateProgramObjectPtr();
320                         
321                         GLint length = (GLint)strlen(fragment_src);
322                         GLhandleARB fragment = glCreateShaderObjectPtr(GL_FRAGMENT_SHADER_ARB);
323                         glShaderSourcePtr(fragment,1,(const GLcharARB**)&fragment_src,&length);
324                         glCompileShaderPtr(fragment);
325                         glAttachObjectPtr(program,fragment);
326                         glDeleteObjectPtr(fragment);
327                 }
328         }
329         
330         if(program) {
331
332                 glLinkProgramPtr(program);
333                 GLint linked;
334                 glGetObjectParameterivPtr(program,GL_OBJECT_LINK_STATUS_ARB,&linked);
335                 if(!linked) {
336                         SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): GLSL error in " << name << " file\n" << get_glsl_error());
337                         return;
338                 }
339                 
340                 glUseProgramObjectPtr(program);
341                 
342                 for(int i = 0; i < 8; i++) {
343                         char texture[32];
344                         sprintf(texture,"s_texture_%d",i);
345                         GLint location = glGetUniformLocationPtr(program,texture);
346                         if(location >= 0) glUniform1iPtr(location,i);
347                 }
348                 
349                 glUseProgramObjectPtr(0);
350                 
351                 glValidateProgramPtr(program);
352                 GLint validated;
353                 glGetObjectParameterivPtr(program,GL_OBJECT_VALIDATE_STATUS_ARB,&validated);
354                 if(!validated) {
355                         SG_LOG(SG_GL, SG_ALERT, "Shader::Shader(): GLSL error in " << name << " file\n" << get_glsl_error());
356                         return;
357                 }
358         }
359         
360         delete [] data;
361 }
362
363 Shader::~Shader() {
364         if(program) glDeleteObjectPtr(program);
365         if(vertex_target == GL_VERTEX_PROGRAM_ARB) glDeleteProgramsPtr(1,&vertex_id);
366         if(fragment_target == GL_FRAGMENT_PROGRAM_ARB) glDeleteProgramsPtr(1,&fragment_id);
367         else if(fragment_target == GL_FRAGMENT_PROGRAM_NV) glDeleteProgramsNVPtr(1,&fragment_id);
368         parameters.clear();
369 }
370
371 /*
372  */
373 const char *Shader::get_error(char *data,int pos) {
374         char *s = data;
375         while(*s && pos--) s++;
376         while(s >= data && *s != '\n') s--;
377         char *e = ++s;
378         while(*e != '\0' && *e != '\n') e++;
379         *e = '\0';
380         return s;
381 }
382
383 /*
384  */
385
386 const char *Shader::get_glsl_error() {
387         GLint length;
388         static char error[4096];
389         glGetInfoLogPtr(program,sizeof(error),&length,error);
390         return error;
391 }
392
393 /*
394  */
395 void Shader::getParameter(const char *name,Parameter *parameter) {
396         if( program ) {
397                 char buf[1024];
398                 strcpy(buf,name);
399                 char *s = strchr(buf,':');
400                 if(s) {
401                         *s++ = '\0';
402                         parameter->length = atoi(s);
403                 } else {
404                         parameter->length = 4;
405                 }
406                 parameter->location = glGetUniformLocationPtr(program,buf);
407         } else if( vertex_id ) {
408                 arb_parameter_list::iterator iParam = arb_parameters.find(name);
409                 if( iParam != arb_parameters.end() )
410                         parameter->location = iParam->second.location;
411                 else
412                         parameter->location = 90;
413                 parameter->length = 4;
414         }
415 }
416
417 /*
418  */
419 void Shader::bindNames(const char *name,...) {
420         Parameter parameter;
421         getParameter(name,&parameter);
422         parameters.push_back(parameter);
423         va_list args;
424         va_start(args,name);
425         while(1) {
426                 const char *name = va_arg(args,const char*);
427                 if(name == NULL) break;
428                 getParameter(name,&parameter);
429                 parameters.push_back(parameter);
430         }
431         va_end(args);
432 }
433
434 /*****************************************************************************/
435 /*                                                                           */
436 /* enable/disable/bind                                                       */
437 /*                                                                           */
438 /*****************************************************************************/
439
440 /*
441  */
442 void Shader::enable() {
443         if(vertex_id) glEnable(vertex_target);
444         if(fragment_id) glEnable(fragment_target);
445 }
446
447 /*
448  */
449 void Shader::disable() {
450         if(program) glUseProgramObjectPtr(0);
451         if(vertex_id) glDisable(vertex_target);
452         if(fragment_id) glDisable(fragment_target);
453 }
454
455 /*
456  */
457 void Shader::bind() {
458         if(program) glUseProgramObjectPtr(program);
459         if(vertex_id) {
460                 if(vertex_target == GL_VERTEX_PROGRAM_ARB) glBindProgramPtr(vertex_target,vertex_id);
461         }
462         if(fragment_id) {
463                 if(fragment_target == GL_FRAGMENT_PROGRAM_ARB) glBindProgramPtr(fragment_target,fragment_id);
464                 else if(fragment_target == GL_FRAGMENT_PROGRAM_NV) glBindProgramNVPtr(fragment_target,fragment_id);
465         }
466 }
467
468 /*
469  */
470 void Shader::bind(const float *v,...) {
471         if(fragment_id) {
472                 if(fragment_target == GL_FRAGMENT_PROGRAM_ARB) glBindProgramPtr(fragment_target,fragment_id);
473                 else if(fragment_target == GL_FRAGMENT_PROGRAM_NV) glBindProgramNVPtr(fragment_target,fragment_id);
474     } else {
475             if(program == 0) {
476                     SG_LOG(SG_GL, SG_ALERT, "Shader::bind(): error GLSL shader isn't loaded\n");
477                     return;
478             }
479             glUseProgramObjectPtr(program);
480     }
481         const float *value = v;
482         va_list args;
483         va_start(args,value);
484         for(int i = 0; i < (int)parameters.size(); i++) {
485                 if( vertex_target ) {
486                         glProgramLocalParameter4fvPtr( vertex_target, parameters[i].location, value);
487                 } else if( program ) {
488                         if(parameters[i].length == 1) glUniform1fvPtr(parameters[i].location,1,value);
489                         else if(parameters[i].length == 2) glUniform2fvPtr(parameters[i].location,1,value);
490                         else if(parameters[i].length == 3) glUniform3fvPtr(parameters[i].location,1,value);
491                         else if(parameters[i].length == 4) glUniform4fvPtr(parameters[i].location,1,value);
492                         else if(parameters[i].length == 9) glUniformMatrix3fvPtr(parameters[i].location,1,false,value);
493                         else if(parameters[i].length == 16) glUniformMatrix4fvPtr(parameters[i].location,1,false,value);
494                 }
495                 value = va_arg(args,const float*);
496                 if(!value) break;
497         }
498         va_end(args);
499 }
500
501 /*****************************************************************************/
502 /*                                                                           */
503 /* set parameters                                                            */
504 /*                                                                           */
505 /*****************************************************************************/
506
507 void Shader::setLocalParameter(int location,const float *value) {
508         if(vertex_target == 0) {
509                 SG_LOG(SG_GL, SG_ALERT, "Shader::setLocalParameter(): error vertex program isn't loaded\n");
510                 return;
511         }
512         glProgramLocalParameter4fvPtr(vertex_target,location,value);
513 }
514
515 void Shader::setEnvParameter(int location,const float *value) {
516         if(vertex_target == 0) {
517                 SG_LOG(SG_GL, SG_ALERT, "Shader::setEnvParameter(): error vertex program isn't loaded\n");
518                 return;
519         }
520         glProgramEnvParameter4fvPtr(vertex_target,location,value);
521 }
522
523 /*
524  */
525 void Shader::setParameter(const char *name,const float *value) {
526         Parameter parameter;
527         getParameter(name,&parameter);
528         if( vertex_target ) {
529                 glProgramLocalParameter4fvPtr( vertex_target, parameter.location, value);
530                 return;
531         }
532         if(program == 0) {
533                 SG_LOG(SG_GL, SG_ALERT, "Shader::setLocalParameter(): error GLSL shader isn't loaded\n");
534                 return;
535         }
536         if(parameter.length == 1) glUniform1fvPtr(parameter.location,1,value);
537         else if(parameter.length == 2) glUniform2fvPtr(parameter.location,1,value);
538         else if(parameter.length == 3) glUniform3fvPtr(parameter.location,1,value);
539         else if(parameter.length == 4) glUniform4fvPtr(parameter.location,1,value);
540         else if(parameter.length == 9) glUniformMatrix3fvPtr(parameter.location,1,false,value);
541         else if(parameter.length == 16) glUniformMatrix4fvPtr(parameter.location,1,false,value);
542 }
543
544 /*
545  */
546 void Shader::setParameters(const float *v,...) {
547         const float *value = v;
548         va_list args;
549         va_start(args,value);
550         for(int i = 0; i < (int)parameters.size(); i++) {
551                 if( vertex_target ) {
552                         glProgramLocalParameter4fvPtr( vertex_target, parameters[i].location, value);
553                 } else if( program ) {
554                         if(parameters[i].length == 1) glUniform1fvPtr(parameters[i].location,1,value);
555                         else if(parameters[i].length == 2) glUniform2fvPtr(parameters[i].location,1,value);
556                         else if(parameters[i].length == 3) glUniform3fvPtr(parameters[i].location,1,value);
557                         else if(parameters[i].length == 4) glUniform4fvPtr(parameters[i].location,1,value);
558                         else if(parameters[i].length == 9) glUniformMatrix3fvPtr(parameters[i].location,1,false,value);
559                         else if(parameters[i].length == 16) glUniformMatrix4fvPtr(parameters[i].location,1,false,value);
560                 }
561                 value = va_arg(args,const float*);
562                 if(!value) break;
563         }
564         va_end(args);
565 }
566
567 #ifndef CONCAT
568 #define CONCAT(a,b) a##b
569 #endif
570 #define mystringify(a) CONCAT(ST,R)(a)
571 #define STR(x) #x
572 #define LOAD_EXT(fn) CONCAT(fn,Ptr) = (CONCAT(fn,Proc)) SGLookupFunction( mystringify(CONCAT(fn,ARB)) )
573
574 void Shader::Init(void) {
575         if( SGIsOpenGLExtensionSupported("GL_ARB_multitexture") )
576                 glGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, &nb_texture_unit );
577         VP_supported = SGIsOpenGLExtensionSupported("GL_ARB_vertex_program");
578         FP_supported = SGIsOpenGLExtensionSupported("GL_ARB_fragment_program");
579         // check that
580         GLSL_supported = SGIsOpenGLExtensionSupported("GL_ARB_shading_language_100") &&
581                 SGIsOpenGLExtensionSupported("GL_ARB_fragment_shader") &&
582                 SGIsOpenGLExtensionSupported("GL_ARB_vertex_shader") &&
583                 SGIsOpenGLExtensionSupported("GL_ARB_shader_objects");
584     NVFP_supported = SGIsOpenGLExtensionSupported("GL_NV_fragment_program");
585
586         if( VP_supported || FP_supported ) {
587                 /* All ARB_fragment_program entry points are shared with ARB_vertex_program. */
588         LOAD_EXT(glVertexAttrib1d);
589         LOAD_EXT( glVertexAttrib1dv );
590         LOAD_EXT( glVertexAttrib1f );
591         LOAD_EXT( glVertexAttrib1fv );
592         LOAD_EXT( glVertexAttrib1s );
593         LOAD_EXT( glVertexAttrib1sv );
594         LOAD_EXT( glVertexAttrib2d );
595         LOAD_EXT( glVertexAttrib2dv );
596         LOAD_EXT( glVertexAttrib2f );
597         LOAD_EXT( glVertexAttrib2fv );
598         LOAD_EXT( glVertexAttrib2s );
599         LOAD_EXT( glVertexAttrib2sv );
600         LOAD_EXT( glVertexAttrib3d );
601         LOAD_EXT( glVertexAttrib3dv );
602         LOAD_EXT( glVertexAttrib3f );
603         LOAD_EXT( glVertexAttrib3fv );
604         LOAD_EXT( glVertexAttrib3s );
605         LOAD_EXT( glVertexAttrib3sv );
606         LOAD_EXT( glVertexAttrib4Nbv );
607         LOAD_EXT( glVertexAttrib4Niv );
608         LOAD_EXT( glVertexAttrib4Nsv );
609         LOAD_EXT( glVertexAttrib4Nub );
610         LOAD_EXT( glVertexAttrib4Nubv );
611         LOAD_EXT( glVertexAttrib4Nuiv );
612         LOAD_EXT( glVertexAttrib4Nusv );
613         LOAD_EXT( glVertexAttrib4bv );
614         LOAD_EXT( glVertexAttrib4d );
615         LOAD_EXT( glVertexAttrib4dv );
616         LOAD_EXT( glVertexAttrib4f );
617         LOAD_EXT( glVertexAttrib4fv );
618         LOAD_EXT( glVertexAttrib4iv );
619         LOAD_EXT( glVertexAttrib4s );
620         LOAD_EXT( glVertexAttrib4sv );
621         LOAD_EXT( glVertexAttrib4ubv );
622         LOAD_EXT( glVertexAttrib4uiv );
623         LOAD_EXT( glVertexAttrib4usv );
624         LOAD_EXT( glVertexAttribPointer );
625         LOAD_EXT( glEnableVertexAttribArray );
626         LOAD_EXT( glDisableVertexAttribArray );
627         LOAD_EXT( glProgramString );
628         LOAD_EXT( glBindProgram );
629         LOAD_EXT( glDeletePrograms );
630         LOAD_EXT( glGenPrograms );
631         LOAD_EXT( glProgramEnvParameter4d );
632         LOAD_EXT( glProgramEnvParameter4dv );
633         LOAD_EXT( glProgramEnvParameter4f );
634         LOAD_EXT( glProgramEnvParameter4fv );
635         LOAD_EXT( glProgramLocalParameter4d );
636         LOAD_EXT( glProgramLocalParameter4dv );
637         LOAD_EXT( glProgramLocalParameter4f );
638         LOAD_EXT( glProgramLocalParameter4fv );
639         LOAD_EXT( glGetProgramEnvParameterdv );
640         LOAD_EXT( glGetProgramEnvParameterfv );
641         LOAD_EXT( glGetProgramLocalParameterdv );
642         LOAD_EXT( glGetProgramLocalParameterfv );
643         LOAD_EXT( glGetProgramiv );
644         LOAD_EXT( glGetProgramString );
645         LOAD_EXT( glGetVertexAttribdv );
646         LOAD_EXT( glGetVertexAttribfv );
647         LOAD_EXT( glGetVertexAttribiv );
648         LOAD_EXT( glGetVertexAttribPointerv );
649         LOAD_EXT( glIsProgram );
650         }
651         if( GLSL_supported ) {
652         LOAD_EXT( glDeleteObject );
653         LOAD_EXT( glGetHandle );
654         LOAD_EXT( glDetachObject );
655         LOAD_EXT( glCreateShaderObject );
656         LOAD_EXT( glShaderSource );
657         LOAD_EXT( glCompileShader );
658         LOAD_EXT( glCreateProgramObject );
659         LOAD_EXT( glAttachObject );
660         LOAD_EXT( glLinkProgram );
661         LOAD_EXT( glUseProgramObject );
662         LOAD_EXT( glValidateProgram );
663         LOAD_EXT( glUniform1f );
664         LOAD_EXT( glUniform2f );
665         LOAD_EXT( glUniform3f );
666         LOAD_EXT( glUniform4f );
667         LOAD_EXT( glUniform1i );
668         LOAD_EXT( glUniform2i );
669         LOAD_EXT( glUniform3i );
670         LOAD_EXT( glUniform4i );
671         LOAD_EXT( glUniform1fv );
672         LOAD_EXT( glUniform2fv );
673         LOAD_EXT( glUniform3fv );
674         LOAD_EXT( glUniform4fv );
675         LOAD_EXT( glUniform1iv );
676         LOAD_EXT( glUniform2iv );
677         LOAD_EXT( glUniform3iv );
678         LOAD_EXT( glUniform4iv );
679         LOAD_EXT( glUniformMatrix2fv );
680         LOAD_EXT( glUniformMatrix3fv );
681         LOAD_EXT( glUniformMatrix4fv );
682         LOAD_EXT( glGetObjectParameterfv );
683         LOAD_EXT( glGetObjectParameteriv );
684         LOAD_EXT( glGetInfoLog );
685         LOAD_EXT( glGetAttachedObjects );
686         LOAD_EXT( glGetUniformLocation );
687         LOAD_EXT( glGetActiveUniform );
688         LOAD_EXT( glGetUniformfv );
689         LOAD_EXT( glGetUniformiv );
690         LOAD_EXT( glGetShaderSource );
691
692         LOAD_EXT( glBindAttribLocation );
693         LOAD_EXT( glGetActiveAttrib );
694         LOAD_EXT( glGetAttribLocation );
695
696         }
697     if( NVFP_supported ) {
698         glBindProgramNVPtr = (glBindProgramNVProc) SGLookupFunction( "glBindProgramNV" );
699         glDeleteProgramsNVPtr = (glDeleteProgramsNVProc) SGLookupFunction( "glDeleteProgramsNV" );
700         glGenProgramsNVPtr = (glGenProgramsNVProc) SGLookupFunction( "glGenProgramsNV" );
701         glLoadProgramNVPtr = (glLoadProgramNVProc) SGLookupFunction( "glLoadProgramNV" );
702         glProgramParameter4fvNVPtr = (glProgramParameter4fvNVProc) SGLookupFunction( "glProgramParameter4fvNV" );
703     }
704 }