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