more graphics patches from Snailrose,
[blender.git] / source / gameengine / Ketsji / BL_Shader.cpp
1 // ------------------------------------
2 #ifdef WIN32
3 #include <windows.h>
4 #endif // WIN32
5 #ifdef __APPLE__
6 #include <OpenGL/gl.h>
7 #include <OpenGL/glu.h>
8 #else
9 #include <GL/gl.h>
10 #include <GL/glu.h>
11 #endif
12
13
14 #include <iostream>
15 #include "BL_Shader.h"
16 #include "BL_Material.h"
17
18 #include "MT_assert.h"
19 #include "MT_Matrix4x4.h"
20 #include "MT_Matrix3x3.h"
21 #include "KX_PyMath.h"
22 #include "MEM_guardedalloc.h"
23
24 #include "RAS_GLExtensionManager.h"
25
26 //using namespace bgl;
27 #define spit(x) std::cout << x << std::endl;
28
29 const bool BL_Shader::Ok()const
30 {
31         return (mShader !=0 && mOk && mUse);
32 }
33
34 BL_Shader::BL_Shader(PyTypeObject *T)
35 :       PyObjectPlus(T),
36         mShader(0),
37         mVert(0),
38         mFrag(0),
39         mPass(1),
40         mOk(0),
41         mUse(0),
42         vertProg(""),
43         fragProg("")
44 {
45         // if !RAS_EXT_support._ARB_shader_objects this class will not be used
46
47         for (int i=0; i<MAXTEX; i++) {
48                 mSampler[i].type = 0;
49                 mSampler[i].pass = 0;
50                 mSampler[i].unit = -1;
51                 mSampler[i].loc  = -1;
52                 mSampler[i].glTexture =0;
53         }
54 }
55
56 using namespace bgl;
57
58 BL_Shader::~BL_Shader()
59 {
60 #ifdef GL_ARB_shader_objects
61         if( mShader ) {
62                 bgl::blDeleteObjectARB(mShader);
63                 mShader = 0;
64         }
65         if( mFrag ) {
66                 bgl::blDeleteObjectARB(mFrag);
67                 mFrag = 0;
68         }
69         if( mVert ) {
70                 bgl::blDeleteObjectARB(mVert);
71                 mVert           = 0;
72         }
73
74         vertProg        = 0;
75         fragProg        = 0;
76         mOk                     = 0;
77
78         bgl::blUseProgramObjectARB(0);
79 #endif//GL_ARB_shader_objects
80 }
81
82
83 bool BL_Shader::LinkProgram()
84 {
85 #ifdef GL_ARB_shader_objects
86         int numchars=0;
87         char* log=0;
88         int vertlen = 0, fraglen=0, proglen=0;
89
90         if(!vertProg || !fragProg){
91                 spit("Invalid GLSL sources");
92                 return false;
93         }
94         
95         // create our objects
96         unsigned int tmpVert = bgl::blCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
97         unsigned int tmpFrag = bgl::blCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
98         unsigned int tmpProg = bgl::blCreateProgramObjectARB();
99
100         if(!tmpVert || !tmpFrag || !tmpProg){
101                 bgl::blDeleteObjectARB(tmpVert);
102                 bgl::blDeleteObjectARB(tmpFrag);
103                 bgl::blDeleteObjectARB(tmpProg);
104                 return false;
105         }
106         // set/compile vertex shader
107         bgl::blShaderSourceARB(tmpVert, 1, (const char**)&vertProg, 0);
108         bgl::blCompileShaderARB(tmpVert);
109         bgl::blGetObjectParameterivARB(tmpVert, GL_OBJECT_INFO_LOG_LENGTH_ARB, &vertlen);
110
111         if( vertlen > 0 && !PrintInfo(vertlen,tmpVert, "Vertex Shader") ){
112                 spit("Vertex shader failed");
113                 bgl::blDeleteObjectARB(tmpVert);
114                 bgl::blDeleteObjectARB(tmpFrag);
115                 bgl::blDeleteObjectARB(tmpProg);
116                 mOk     = 0;
117                 return false;
118         }
119         // set/compile fragment shader
120         bgl::blShaderSourceARB(tmpFrag, 1,(const char**)&fragProg, 0);
121         bgl::blCompileShaderARB(tmpFrag);
122         bgl::blGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, &fraglen);
123         if(fraglen >0 && !PrintInfo(fraglen,tmpFrag, "Fragment Shader") ){
124                 spit("Fragment shader failed");
125                 bgl::blDeleteObjectARB(tmpVert);
126                 bgl::blDeleteObjectARB(tmpFrag);
127                 bgl::blDeleteObjectARB(tmpProg);
128                 mOk     = 0;
129                 return false;
130         }
131
132         // set compiled vert/frag shader & link
133         bgl::blAttachObjectARB(tmpProg, tmpVert);
134         bgl::blAttachObjectARB(tmpProg, tmpFrag);
135         bgl::blLinkProgramARB(tmpProg);
136
137         bgl::blGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, &proglen);
138         if(proglen > 0){
139                 PrintInfo(proglen,tmpProg, "GLSL Shader");
140         }
141         else{
142                 spit("Program failed");
143                 bgl::blDeleteObjectARB(tmpVert);
144                 bgl::blDeleteObjectARB(tmpFrag);
145                 bgl::blDeleteObjectARB(tmpProg);
146                 mOk     = 0;
147                 return false;
148         }
149
150         // set
151         mShader = tmpProg;
152         mVert   = tmpVert;
153         mFrag   = tmpFrag;
154         mOk             = 1;
155         return true;
156 #else
157         return false;
158 #endif//GL_ARB_shader_objects
159 }
160
161 bool BL_Shader::PrintInfo(int len, unsigned int handle, const char *type)
162 {
163 #ifdef GL_ARB_shader_objects
164         int numchars=0;
165         char *log = (char*)MEM_mallocN(sizeof(char)*len, "print_log");
166         if(!log) {
167                 spit("BL_Shader::PrintInfo() MEM_mallocN failed");
168                 return false;
169         }
170         bgl::blGetInfoLogARB(handle, len, &numchars, log);
171         
172         if(numchars >0){
173                 spit(type);
174                 spit(log);
175                 MEM_freeN(log);
176                 log=0;
177                 return false;
178         }
179         MEM_freeN(log);
180         log=0;
181         return true;
182 #else
183         return false
184 #endif//GL_ARB_shader_objects
185 }
186
187
188 char *BL_Shader::GetVertPtr()
189 {
190         return vertProg?vertProg:0;
191 }
192
193 char *BL_Shader::GetFragPtr()
194 {
195         return fragProg?fragProg:0;
196 }
197
198 void BL_Shader::SetVertPtr( char *vert )
199 {
200         vertProg = vert;
201 }
202
203 void BL_Shader::SetFragPtr( char *frag )
204 {
205         fragProg = frag;
206 }
207
208 unsigned int BL_Shader::GetProg()
209
210         return mShader;
211 }
212
213 unsigned int BL_Shader::GetVertexShader()
214
215         return mVert;  
216 }
217
218 unsigned int BL_Shader::GetFragmentShader()
219
220         return mFrag;  
221 }
222
223 const uSampler* BL_Shader::getSampler(int i)
224 {
225         MT_assert(i<=MAXTEX);
226         return &mSampler[i];
227 }
228
229 void BL_Shader::InitializeSampler(
230         int type,
231         int unit,
232         int pass,
233         unsigned int texture)
234 {
235         MT_assert(unit<=MAXTEX);
236         mSampler[unit].glTexture = texture;
237         mSampler[unit].loc =-1;
238         mSampler[unit].pass=0;
239         mSampler[unit].type=type;
240         mSampler[unit].unit=unit;
241 }
242
243 PyObject* BL_Shader::_getattr(const STR_String& attr)
244 {
245         _getattr_up(PyObjectPlus);
246 }
247
248
249 PyMethodDef BL_Shader::Methods[] = 
250 {
251         // creation
252         KX_PYMETHODTABLE( BL_Shader, setSource ),
253         KX_PYMETHODTABLE( BL_Shader, delSource ),
254         KX_PYMETHODTABLE( BL_Shader, getVertexProg ),
255         KX_PYMETHODTABLE( BL_Shader, getFragmentProg ),
256         KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ),
257         KX_PYMETHODTABLE( BL_Shader, validate),
258         /// access functions
259         KX_PYMETHODTABLE( BL_Shader, isValid),
260         KX_PYMETHODTABLE( BL_Shader, setUniform1f ),
261         KX_PYMETHODTABLE( BL_Shader, setUniform2f ),
262         KX_PYMETHODTABLE( BL_Shader, setUniform3f ),
263         KX_PYMETHODTABLE( BL_Shader, setUniform4f ),
264         KX_PYMETHODTABLE( BL_Shader, setUniform1i ),
265         KX_PYMETHODTABLE( BL_Shader, setUniform2i ),
266         KX_PYMETHODTABLE( BL_Shader, setUniform3i ),
267         KX_PYMETHODTABLE( BL_Shader, setUniform4i ),
268
269         KX_PYMETHODTABLE( BL_Shader, setUniformfv ),
270         KX_PYMETHODTABLE( BL_Shader, setUniformiv ),
271
272         KX_PYMETHODTABLE( BL_Shader, setSampler  ),
273         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ),
274         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ),
275
276         {NULL,NULL} //Sentinel
277 };
278
279
280 PyTypeObject BL_Shader::Type = {
281         PyObject_HEAD_INIT(&PyType_Type)
282                 0,
283                 "BL_Shader",
284                 sizeof(BL_Shader),
285                 0,
286                 PyDestructor,
287                 0,
288                 __getattr,
289                 __setattr,
290                 0,
291                 __repr,
292                 0
293 };
294
295
296 PyParentObject BL_Shader::Parents[] = {
297         &PyObjectPlus::Type,
298         &BL_Shader::Type,
299         NULL
300 };
301
302
303 KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" )
304 {
305 #ifdef GL_ARB_shader_objects
306         if(mShader !=0 && mOk  )
307         {
308                 // already set...
309                 Py_Return;
310         }
311
312         char *v,*f;
313         int apply=0;
314         if( PyArg_ParseTuple(args, "ssi", &v, &f, &apply) )
315         {
316                 vertProg = v;
317                 fragProg = f;
318                 if( LinkProgram() ) {
319                         bgl::blUseProgramObjectARB( mShader );
320                         mUse = apply!=0;
321                         Py_Return;
322                 }
323                 vertProg = 0;
324                 fragProg = 0;
325                 mUse = 0;
326                 bgl::blUseProgramObjectARB( 0 );
327                 PyErr_Format(PyExc_ValueError, "GLSL Error");
328         }
329         return NULL;
330 #else
331         Py_Return;
332 #endif
333 }
334
335
336 KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" )
337 {
338 #ifdef GL_ARB_shader_objects
339         bgl::blDeleteObjectARB(mShader);
340         bgl::blDeleteObjectARB(mFrag);
341         bgl::blDeleteObjectARB(mVert);
342         mShader         = 0;
343         mFrag           = 0;
344         mVert           = 0;
345         vertProg        = 0;
346         fragProg        = 0;
347         mOk                     = 0;
348         mUse            = 0;
349         bgl::blUseProgramObjectARB(0);
350 #endif
351         Py_Return;
352
353 }
354
355 KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" )
356 {
357         return PyInt_FromLong( ( mShader !=0 &&  mOk ) );
358 }
359
360 KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" )
361 {
362         return PyString_FromString(vertProg?vertProg:"");
363 }
364
365 KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" )
366 {
367         return PyString_FromString(fragProg?fragProg:"");
368 }
369
370 KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()")
371 {
372 #ifdef GL_ARB_shader_objects
373         if(mShader==0) {
374                 PyErr_Format(PyExc_TypeError, "invalid shader object");
375                 return NULL;
376         }
377         int stat = 0;
378         bgl::blValidateProgramARB(mShader);
379         bgl::blGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB, &stat);
380         return PyInt_FromLong(!PrintInfo(stat, mShader, "Validation"));
381 #else
382         Py_Return;
383 #endif//GL_ARB_shader_objects
384 }
385
386
387 KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
388 {
389 #ifdef GL_ARB_shader_objects
390         char *uniform="";
391         int index=-1;
392         if(PyArg_ParseTuple(args, "si", &uniform, &index)) 
393         {
394                 if(mShader==0)
395                 {
396                         PyErr_Format(PyExc_ValueError, "invalid shader object");
397                         return NULL;
398                 }
399                 int loc= bgl::blGetUniformLocationARB(mShader, uniform);
400                 if( loc==-1 )
401                 {
402                         spit("Invalid uniform value: " << uniform << ".");
403                         Py_Return;
404                 }else
405                 {
406                         if(index <= MAXTEX)
407                         {
408                                 mSampler[index].loc = loc;
409                         }else
410                         {
411                                 spit("Invalid texture sample index: " << index);
412                         }
413                         Py_Return;
414                 }
415         }
416         return NULL;
417 #else
418         Py_Return;
419 #endif//GL_ARB_shader_objects
420 }
421
422 KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" )
423 {
424         int pass = 1;
425         if(!PyArg_ParseTuple(args, "i", &pass))
426                 return NULL;
427
428         mPass = 1;
429         Py_Return;
430 }
431
432 /// access functions
433 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
434 {
435 #ifdef GL_ARB_shader_objects
436         char *uniform="";
437         float value=0;
438         if(PyArg_ParseTuple(args, "sf", &uniform, &value ))
439         {
440                 if( mShader==0 )
441                 {
442                         PyErr_Format(PyExc_ValueError, "invalid shader object");
443                         return NULL;
444                 }
445                 int loc= bgl::blGetUniformLocationARB(mShader, uniform);
446                 if( loc==-1 )
447                 {
448                         spit("Invalid uniform value: " << uniform << ".");
449                         Py_Return;
450                 }else
451                 {
452                         bgl::blUseProgramObjectARB( mShader );
453                         bgl::blUniform1fARB( loc, value );
454                         Py_Return;
455                 }
456
457         }
458         return NULL;
459 #else
460         Py_Return;
461 #endif
462 }
463
464
465 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
466 {
467 #ifdef GL_ARB_shader_objects
468         char *uniform="";
469         float array[2]={ 0,0 };
470         if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] ))
471         {
472                 if( mShader==0 )
473                 {
474                         PyErr_Format(PyExc_ValueError, "invalid shader object");
475                         return NULL;
476                 }
477                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
478                 if( loc==-1 )
479                 {
480                         spit("Invalid uniform value: " << uniform << ".");
481                         Py_Return;
482                 }else
483                 {
484                         bgl::blUseProgramObjectARB( mShader );
485                         bgl::blUniform2fARB(loc, array[0],array[1] );
486                         Py_Return;
487                 }
488
489         }
490         return NULL;
491 #else
492         Py_Return;
493 #endif//GL_ARB_shader_objects
494 }
495
496
497 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
498 {
499 #ifdef GL_ARB_shader_objects
500         char *uniform="";
501         float array[3]={0,0,0};
502         if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2]))
503         {
504                 if(mShader==0)
505                 {
506                         PyErr_Format(PyExc_ValueError, "invalid shader object");
507                         return NULL;
508                 }
509                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
510                 if( loc==-1 )
511                 {
512                         spit("Invalid uniform value: " << uniform << ".");
513                         Py_Return;
514                 }else
515                 {
516                         bgl::blUseProgramObjectARB(mShader);
517                         bgl::blUniform3fARB(loc, array[0],array[1],array[2]);
518                         Py_Return;
519                 }
520
521         }
522         return NULL;
523 #else
524         Py_Return;
525 #endif//GL_ARB_shader_objects
526 }
527
528
529 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
530 {
531 #ifdef GL_ARB_shader_objects
532         char *uniform="";
533         float array[4]={0,0,0,0};
534         if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3]))
535         {
536                 if(mShader==0)
537                 {
538                         PyErr_Format(PyExc_ValueError, "invalid shader object");
539                         return NULL;
540                 }
541                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
542                 if( loc==-1 )
543                 {
544                         spit("Invalid uniform value: " << uniform << ".");
545                         Py_Return;
546                 }else
547                 {
548                         bgl::blUseProgramObjectARB(mShader);
549                         bgl::blUniform4fARB(loc, array[0],array[1],array[2], array[3]);
550                         Py_Return;
551                 }
552         }
553         return NULL;
554 #else
555         Py_Return;
556 #endif//GL_ARB_shader_objects
557 }
558
559
560 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
561 {
562 #ifdef GL_ARB_shader_objects
563         char *uniform="";
564         int value=0;
565         if(PyArg_ParseTuple(args, "si", &uniform, &value ))
566         {
567                 if( mShader==0 )
568                 {
569                         PyErr_Format(PyExc_ValueError, "invalid shader object");
570                         return NULL;
571                 }
572                 int loc= bgl::blGetUniformLocationARB(mShader, uniform);
573                 if( loc==-1 )
574                 {
575                         spit("Invalid uniform value: " << uniform << ".");
576                         Py_Return;
577                 }else
578                 {
579                         bgl::blUseProgramObjectARB( mShader );
580                         bgl::blUniform1iARB( loc, value );
581                         Py_Return;
582                 }
583         }
584         return NULL;
585 #else
586         Py_Return;
587 #endif//GL_ARB_shader_objects
588 }
589
590
591 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
592 {
593 #ifdef GL_ARB_shader_objects
594         char *uniform="";
595         int array[2]={ 0,0 };
596         if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] ))
597         {
598                 if( mShader==0 )
599                 {
600                         PyErr_Format(PyExc_ValueError, "invalid shader object");
601                         return NULL;
602                 }
603                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
604                 if( loc==-1 )
605                 {
606                         spit("Invalid uniform value: " << uniform << ".");
607                         Py_Return;
608                 }else
609                 {
610                         bgl::blUseProgramObjectARB( mShader );
611                         bgl::blUniform2iARB(loc, array[0],array[1] );
612                         Py_Return;
613                 }
614         }
615         return NULL;
616 #else
617         Py_Return;
618 #endif//GL_ARB_shader_objects
619 }
620
621
622 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
623 {
624 #ifdef GL_ARB_shader_objects
625         char *uniform="";
626         int array[3]={0,0,0};
627         if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2]))
628         {
629                 if(mShader==0)
630                 {
631                         PyErr_Format(PyExc_ValueError, "invalid shader object");
632                         return NULL;
633                 }
634                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
635                 if( loc==-1 )
636                 {
637                         spit("Invalid uniform value: " << uniform << ".");
638                         Py_Return;
639                 }else
640                 {
641                         bgl::blUseProgramObjectARB(mShader);
642                         bgl::blUniform3iARB(loc, array[0],array[1],array[2]);
643                         Py_Return;
644                 }
645         }
646         return NULL;
647 #else
648         Py_Return;
649 #endif//GL_ARB_shader_objects
650 }
651
652 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
653 {
654 #ifdef GL_ARB_shader_objects
655         char *uniform="";
656         int array[4]={0,0,0, 0};
657         if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] ))
658         {
659                 if(mShader==0)
660                 {
661                         PyErr_Format(PyExc_ValueError, "invalid shader object");
662                         return NULL;
663                 }
664                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
665                 if( loc==-1 )
666                 {
667                         spit("Invalid uniform value: " << uniform << ".");
668                         Py_Return;
669                 }else
670                 {
671                         bgl::blUseProgramObjectARB(mShader);
672                         bgl::blUniform4iARB(loc, array[0],array[1],array[2], array[3]);
673                         Py_Return;
674                 }
675         }
676         return NULL;
677 #else
678         Py_Return;
679 #endif//GL_ARB_shader_objects
680 }
681
682 KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )")
683 {
684 #ifdef GL_ARB_shader_objects
685         char*uniform = "";
686         PyObject *listPtr =0;
687         float array_data[4] = {0.f,0.f,0.f,0.f};
688
689         if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
690         {
691                 if(mShader==0)
692                 {
693                         PyErr_Format(PyExc_ValueError, "invalid shader object");
694                         return NULL;
695                 }
696                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
697                 if( loc==-1 )
698                 {
699                         spit("Invalid uniform value: " << uniform << ".");
700                         Py_Return;
701                 }else
702                 {
703                         if(PySequence_Check(listPtr))
704                         {
705                                 unsigned int list_size = PySequence_Size(listPtr);
706                                 
707                                 for(unsigned int i=0; (i<list_size && i<=4); i++)
708                                 {
709                                         PyObject *item = PySequence_GetItem(listPtr, i);
710                                         array_data[i] = (float)PyFloat_AsDouble(item);
711                                         Py_DECREF(item);
712                                 }
713                                 switch(list_size)
714                                 {
715                                 case 2:
716                                         {
717                                                 bgl::blUseProgramObjectARB(mShader);
718                                                 bgl::blUniform2fARB(loc, array_data[0],array_data[1]);
719                                                 Py_Return;
720                                         } break;
721                                 case 3:
722                                         {
723                                                 bgl::blUseProgramObjectARB(mShader);
724                                                 bgl::blUniform3fARB(loc, array_data[0],array_data[1], array_data[2]);
725                                                 Py_Return;
726                                         }break;
727                                 case 4:
728                                         {
729                                                 bgl::blUseProgramObjectARB(mShader);
730                                                 bgl::blUniform4fARB(loc, array_data[0],array_data[1], array_data[2], array_data[3]);
731                                                 Py_Return;
732                                         }break;
733                                 default:
734                                         {
735                                                 PyErr_Format(PyExc_TypeError, "Invalid list size");
736                                                 return NULL;
737                                         }break;
738                                 }
739                         }
740                 }
741         }
742         return NULL;
743 #else
744         Py_Return;
745 #endif//GL_ARB_shader_objects
746
747 }
748
749 KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 or list4) )")
750 {
751 #ifdef GL_ARB_shader_objects
752         char*uniform = "";
753         PyObject *listPtr =0;
754         int array_data[4] = {0,0,0,0};
755
756         if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
757         {
758                 if(mShader==0)
759                 {
760                         PyErr_Format(PyExc_ValueError, "invalid shader object");
761                         return NULL;
762                 }
763                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
764                 if( loc==-1 )
765                 {
766                         spit("Invalid uniform value: " << uniform << ".");
767                         Py_Return;
768                 }else
769                 {
770                         if(PySequence_Check(listPtr))
771                         {
772                                 unsigned int list_size = PySequence_Size(listPtr);
773                                 
774                                 for(unsigned int i=0; (i<list_size && i<=4); i++)
775                                 {
776                                         PyObject *item = PySequence_GetItem(listPtr, i);
777                                         array_data[i] = PyInt_AsLong(item);
778                                         Py_DECREF(item);
779                                 }
780                                 switch(list_size)
781                                 {
782                                 case 2:
783                                         {
784                                                 bgl::blUseProgramObjectARB(mShader);
785                                                 bgl::blUniform2iARB(loc, array_data[0],array_data[1]);
786                                                 Py_Return;
787                                         } break;
788                                 case 3:
789                                         {
790                                                 bgl::blUseProgramObjectARB(mShader);
791                                                 bgl::blUniform3iARB(loc, array_data[0],array_data[1], array_data[2]);
792                                                 Py_Return;
793                                         }break;
794                                 case 4:
795                                         {
796                                                 bgl::blUseProgramObjectARB(mShader);
797                                                 bgl::blUniform4iARB(loc, array_data[0],array_data[1], array_data[2], array_data[3]);
798                                                 Py_Return;
799                                         }break;
800                                 default:
801                                         {
802                                                 PyErr_Format(PyExc_TypeError, "Invalid list size");
803                                                 return NULL;
804                                         }break;
805                                 }
806                         }
807                 }
808         }
809         return NULL;
810 #else
811         Py_Return;
812 #endif//GL_ARB_shader_objects
813 }
814
815
816 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 
817 "setUniformMatrix4(uniform-name, mat-4x4, transpose(row-major=true, col-major=false)" )
818 {
819 #ifdef GL_ARB_shader_objects
820         float matr[16] = {
821                 1,0,0,0,
822                 0,1,0,0,
823                 0,0,1,0,
824                 0,0,0,1
825         };
826
827         char *uniform="";
828         PyObject *matrix=0;
829         int transp=1; // MT_ is row major so transpose by default....
830         if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
831         {
832                 if(mShader==0)
833                 {
834                         PyErr_Format(PyExc_ValueError, "invalid shader object");
835                         return NULL;
836                 }
837                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
838                 if( loc==-1 )
839                 {
840                         spit("Invalid uniform value: " << uniform << ".");
841                         Py_Return;
842                 }else
843                 {
844                         if (PyObject_IsMT_Matrix(matrix, 4))
845                         {
846                                 MT_Matrix4x4 mat;
847                                 if (PyMatTo(matrix, mat))
848                                 {
849                                         mat.getValue(matr);
850                                         bgl::blUseProgramObjectARB(mShader);
851                                         bgl::blUniformMatrix4fvARB(loc, 1, (transp!=0)?GL_TRUE:GL_FALSE, matr);
852                                         Py_Return;
853                                 }
854                         }
855                 }
856         }
857         return NULL;
858 #else
859         Py_Return;
860 #endif//GL_ARB_shader_objects
861 }
862
863
864 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
865 "setUniformMatrix3(uniform-name, list[3x3], transpose(row-major=true, col-major=false)" )
866 {
867 #ifdef GL_ARB_shader_objects
868         float matr[9] = {
869                 1,0,0,
870                 0,1,0,
871                 0,0,1,
872         };
873
874         char *uniform="";
875         PyObject *matrix=0;
876         int transp=1; // MT_ is row major so transpose by default....
877         if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
878         {
879                 if(mShader==0)
880                 {
881                         PyErr_Format(PyExc_ValueError, "invalid shader object");
882                         return NULL;
883                 }
884                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
885                 if( loc==-1 )
886                 {
887                         spit("Invalid uniform value: " << uniform << ".");
888                         Py_Return;
889                 }else
890                 {
891                         if (PyObject_IsMT_Matrix(matrix, 3))
892                         {
893                                 MT_Matrix3x3 mat;
894                                 if (PyMatTo(matrix, mat))
895                                 {
896                                         mat.getValue(matr);
897                                         bgl::blUseProgramObjectARB(mShader);
898                                         bgl::blUniformMatrix3fvARB(loc, 1, (transp!=0)?GL_TRUE:GL_FALSE, matr);
899                                         Py_Return;
900                                 }
901                         }
902                 }
903         }
904         return NULL;
905 #else
906         Py_Return;
907 #endif//GL_ARB_shader_objects
908 }