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