Improved OpenGL Shader Language support for game engine. The python interface is...
[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 #include "RAS_MeshObject.h"
27 #include "RAS_IRasterizer.h"
28
29 //using namespace bgl;
30 #define spit(x) std::cout << x << std::endl;
31
32 const bool BL_Shader::Ok()const
33 {
34         return (mShader !=0 && mOk && mUse);
35 }
36
37
38 BL_Shader::BL_Shader(PyTypeObject *T)
39 :       PyObjectPlus(T),
40         mShader(0),
41         mPass(1),
42         mOk(0),
43         mUse(0),
44         vertProg(""),
45         fragProg(""),
46         mError(0),
47         mAttr(0),
48         mPreDefLoc(-1),
49         mPreDefType(-1),
50         mDeleteTexture(0)
51 {
52         // if !RAS_EXT_support._ARB_shader_objects this class will not be used
53
54         for (int i=0; i<MAXTEX; i++) {
55                 mSampler[i].type = 0;
56                 mSampler[i].pass = 0;
57                 mSampler[i].unit = -1;
58                 mSampler[i].loc  = -1;
59                 mSampler[i].gl_texture = 0;
60                 mSampler[i].flag=0;
61         }
62 }
63
64 using namespace bgl;
65
66 BL_Shader::~BL_Shader()
67 {
68 #ifdef GL_ARB_shader_objects
69         for (int i=0; i<MAXTEX; i++) 
70         {
71                 if(mSampler[i].flag & OWN)
72                 {
73                         if(mSampler[i].gl_texture)
74                                 mSampler[i].gl_texture->DeleteTex();
75                 }
76         }
77         if( mShader ) {
78                 bgl::blDeleteObjectARB(mShader);
79                 mShader = 0;
80         }
81         vertProg        = 0;
82         fragProg        = 0;
83         mOk                     = 0;
84
85         bgl::blUseProgramObjectARB(0);
86 #endif//GL_ARB_shader_objects
87 }
88
89
90 bool BL_Shader::LinkProgram()
91 {
92 #ifdef GL_ARB_shader_objects
93
94         int vertlen = 0, fraglen=0, proglen=0;
95         int vertstatus=0, fragstatus=0, progstatus=0;
96         unsigned int tmpVert=0, tmpFrag=0, tmpProg=0;
97         int char_len=0;
98
99         if(mError)
100                 goto programError;
101
102         if(!vertProg || !fragProg){
103                 spit("Invalid GLSL sources");
104                 return false;
105         }
106         if( !RAS_EXT_support._ARB_fragment_shader) {
107                 spit("Fragment shaders not supported");
108                 return false;
109         }
110         if( !RAS_EXT_support._ARB_vertex_shader) {
111                 spit("Vertex shaders not supported");
112                 return false;
113         }
114         
115         // -- vertex shader ------------------
116         tmpVert = bgl::blCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
117         bgl::blShaderSourceARB(tmpVert, 1, (const char**)&vertProg, 0);
118         bgl::blCompileShaderARB(tmpVert);
119         bgl::blGetObjectParameterivARB(tmpVert, GL_OBJECT_INFO_LOG_LENGTH_ARB, &vertlen);
120         
121         // print info if any
122         if( vertlen > 0){
123                 STR_String str("",vertlen);
124                 bgl::blGetInfoLogARB(tmpVert, vertlen, &char_len, str.Ptr());
125                 if(char_len >0) {
126                         spit("---- Vertex Shader Error ----");
127                         spit(str.ReadPtr());
128                 }
129                 str.Clear();
130         }
131         // check for compile errors
132         bgl::blGetObjectParameterivARB(tmpVert, GL_OBJECT_COMPILE_STATUS_ARB, &vertstatus);
133         if(!vertstatus) {
134                 spit("---- Vertex shader failed to compile ----");
135                 goto programError;
136         }
137
138         // -- fragment shader ----------------
139         tmpFrag = bgl::blCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
140         bgl::blShaderSourceARB(tmpFrag, 1,(const char**)&fragProg, 0);
141         bgl::blCompileShaderARB(tmpFrag);
142         bgl::blGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, &fraglen);
143         if(fraglen >0 ){
144                 STR_String str("",fraglen);
145                 bgl::blGetInfoLogARB(tmpFrag, fraglen, &char_len, str.Ptr());
146                 if(char_len >0) {
147                         spit("---- Fragment Shader Error ----");
148                         spit(str.ReadPtr());
149                 }
150                 str.Clear();
151         }
152
153         bgl::blGetObjectParameterivARB(tmpFrag, GL_OBJECT_COMPILE_STATUS_ARB, &fragstatus);
154         if(!fragstatus){
155                 spit("---- Fragment shader failed to compile ----");
156                 goto programError;
157         }
158
159         
160         // -- program ------------------------
161         //  set compiled vert/frag shader & link
162         tmpProg = bgl::blCreateProgramObjectARB();
163         bgl::blAttachObjectARB(tmpProg, tmpVert);
164         bgl::blAttachObjectARB(tmpProg, tmpFrag);
165         bgl::blLinkProgramARB(tmpProg);
166         bgl::blGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, &proglen);
167         bgl::blGetObjectParameterivARB(tmpProg, GL_OBJECT_LINK_STATUS_ARB, &progstatus);
168         
169
170         if(proglen > 0) {
171                 STR_String str("",proglen);
172                 bgl::blGetInfoLogARB(tmpProg, proglen, &char_len, str.Ptr());
173                 if(char_len >0) {
174                         spit("---- GLSL Program ----");
175                         spit(str.ReadPtr());
176                 }
177                 str.Clear();
178         }
179
180         if(!progstatus){
181                 spit("---- GLSL program failed to link ----");
182                 goto programError;
183         }
184
185         // set
186         mShader = tmpProg;
187         bgl::blDeleteObjectARB(tmpVert);
188         bgl::blDeleteObjectARB(tmpFrag);
189         mOk             = 1;
190         mError = 0;
191         return true;
192
193 programError:
194         if(tmpVert) {
195                 bgl::blDeleteObjectARB(tmpVert);
196                 tmpVert=0;
197         }
198         if(tmpFrag) {
199                 bgl::blDeleteObjectARB(tmpFrag);
200                 tmpFrag=0;
201         }
202
203         if(tmpProg) {
204                 bgl::blDeleteObjectARB(tmpProg);
205                 tmpProg=0;
206         }
207
208         mOk             = 0;
209         mUse    = 0;
210         mError  = 1;
211         return false;
212 #else
213         return false;
214 #endif//GL_ARB_shader_objects
215 }
216
217 char *BL_Shader::GetVertPtr()
218 {
219         return vertProg?vertProg:0;
220 }
221
222 char *BL_Shader::GetFragPtr()
223 {
224         return fragProg?fragProg:0;
225 }
226
227 void BL_Shader::SetVertPtr( char *vert )
228 {
229         vertProg = vert;
230 }
231
232 void BL_Shader::SetFragPtr( char *frag )
233 {
234         fragProg = frag;
235 }
236
237 unsigned int BL_Shader::GetProg()
238
239         return mShader;
240 }
241
242 const uSampler* BL_Shader::getSampler(int i)
243 {
244         MT_assert(i<=MAXTEX);
245         return &mSampler[i];
246 }
247
248 void BL_Shader::SetSampler(int loc, int unit)
249 {
250 #ifdef GL_ARB_shader_objects
251         if( RAS_EXT_support._ARB_fragment_shader &&
252                 RAS_EXT_support._ARB_vertex_shader &&
253                 RAS_EXT_support._ARB_shader_objects 
254                 )
255         {
256                 bgl::blUniform1iARB(loc, unit);
257         }
258 #endif
259 }
260
261
262 void BL_Shader::InitializeSampler(
263         int type,
264         int unit,
265         int pass,
266         BL_Texture* texture)
267 {
268         MT_assert(unit<=MAXTEX);
269         mSampler[unit].gl_texture = texture;
270         mSampler[unit].loc =-1;
271         mSampler[unit].pass=0;
272         mSampler[unit].type=type;
273         mSampler[unit].unit=unit;
274         mSampler[unit].flag = 0;
275 }
276
277
278 void BL_Shader::SetProg(bool enable)
279 {
280 #ifdef GL_ARB_shader_objects
281         if( RAS_EXT_support._ARB_fragment_shader &&
282                 RAS_EXT_support._ARB_vertex_shader &&
283                 RAS_EXT_support._ARB_shader_objects 
284                 )
285         {
286                 if(     mShader != 0 && mOk && enable) {
287                         bgl::blUseProgramObjectARB(mShader);
288                 }
289                 else {
290                         bgl::blUseProgramObjectARB(0);  
291                 }
292         }
293 #endif
294 }
295
296 void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty )
297 {
298 #ifdef GL_ARB_shader_objects
299         if(!Ok()) return;
300
301         if( RAS_EXT_support._ARB_fragment_shader &&
302                 RAS_EXT_support._ARB_vertex_shader &&
303                 RAS_EXT_support._ARB_shader_objects 
304                 )
305         {
306                 MT_Matrix4x4 model;
307                 model.setValue(ms.m_OpenGLMatrix);
308                 MT_Matrix4x4 view;
309                 rasty->GetViewMatrix(view);
310                 switch (mPreDefType)
311                 {
312                         case MODELMATRIX:
313                                 {
314                                         SetUniform(mPreDefLoc, model);
315                                         break;
316                                 }
317                         case MODELMATRIX_TRANSPOSE:
318                                 {
319                                         SetUniform(mPreDefLoc, model, true);
320                                         break;
321                                 }
322                         case MODELMATRIX_INVERSE:
323                                 {
324                                         model.invert();
325                                         SetUniform(mPreDefLoc, model);
326                                         break;
327                                 }
328                         case MODELMATRIX_INVERSETRANSPOSE:
329                                 {
330                                         model.invert();
331                                         SetUniform(mPreDefLoc, model, true);
332                                         break;
333                                 }
334                         case MODELVIEWMATRIX:
335                                 {
336                                         SetUniform(mPreDefLoc, view*model);
337                                         break;
338                                 }
339
340                         case MODELVIEWMATRIX_TRANSPOSE:
341                                 {
342                                         MT_Matrix4x4 mat(view*model);
343                                         SetUniform(mPreDefLoc, mat, true);
344                                         break;
345                                 }
346                         case MODELVIEWMATRIX_INVERSE:
347                                 {
348                                         MT_Matrix4x4 mat(view*model);
349                                         mat.invert();
350                                         SetUniform(mPreDefLoc, mat);
351                                         break;
352                                 }
353                         case MODELVIEWMATRIX_INVERSETRANSPOSE:
354                                 {
355                                         MT_Matrix4x4 mat(view*model);
356                                         mat.invert();
357                                         SetUniform(mPreDefLoc, mat, true);
358                                         break;
359                                 }
360                         case CAM_POS:
361                                 {
362                                         MT_Point3 pos(rasty->GetCameraPosition());
363                                         SetUniform(mPreDefLoc, pos);
364                                         break;
365                                 }
366                         case VIEWMATRIX:
367                                 {
368                                         SetUniform(mPreDefLoc, view);
369                                         break;
370                                 }
371                         case VIEWMATRIX_TRANSPOSE:
372                                 {
373                                         SetUniform(mPreDefLoc, view, true);
374                                         break;
375                                 }
376                         case VIEWMATRIX_INVERSE:
377                                 {
378                                         view.invert();
379                                         SetUniform(mPreDefLoc, view);
380                                         break;
381                                 }
382                         case VIEWMATRIX_INVERSETRANSPOSE:
383                                 {
384                                         view.invert();
385                                         SetUniform(mPreDefLoc, view, true);
386                                         break;
387                                 }
388                         default:
389                                 break;
390                 }
391         }
392 #endif
393 }
394
395
396 int BL_Shader::GetAttribLocation(const STR_String& name)
397 {
398 #ifdef GL_ARB_shader_objects
399         if( RAS_EXT_support._ARB_fragment_shader &&
400                 RAS_EXT_support._ARB_vertex_shader &&
401                 RAS_EXT_support._ARB_shader_objects 
402                 )
403         {
404                 return bgl::blGetAttribLocationARB(mShader, name.ReadPtr());
405         }
406 #endif
407         return -1;
408 }
409
410 void BL_Shader::BindAttribute(const STR_String& attr, int loc)
411 {
412 #ifdef GL_ARB_shader_objects
413         if( RAS_EXT_support._ARB_fragment_shader &&
414                 RAS_EXT_support._ARB_vertex_shader &&
415                 RAS_EXT_support._ARB_shader_objects 
416                 )
417         {
418                 bgl::blBindAttribLocationARB(mShader, loc, attr.ReadPtr());
419         }
420 #endif
421 }
422
423 int BL_Shader::GetUniformLocation(const STR_String& name)
424 {
425 #ifdef GL_ARB_shader_objects
426         if( RAS_EXT_support._ARB_fragment_shader &&
427                 RAS_EXT_support._ARB_vertex_shader &&
428                 RAS_EXT_support._ARB_shader_objects 
429                 )
430         {
431                 return bgl::blGetUniformLocationARB(mShader, name.ReadPtr());
432         }
433 #endif
434         return -1;
435 }
436
437 void BL_Shader::SetUniform(int uniform, const MT_Tuple2& vec)
438 {
439 #ifdef GL_ARB_shader_objects
440         if( RAS_EXT_support._ARB_fragment_shader &&
441                 RAS_EXT_support._ARB_vertex_shader &&
442                 RAS_EXT_support._ARB_shader_objects 
443                 )
444         {
445                 float value[2];
446                 vec.getValue(value);
447                 bgl::blUniform2fvARB(uniform, 1, value);
448         }
449 #endif
450
451 }
452
453 void BL_Shader::SetUniform(int uniform, const MT_Tuple3& vec)
454 {
455 #ifdef GL_ARB_shader_objects
456         if( RAS_EXT_support._ARB_fragment_shader &&
457                 RAS_EXT_support._ARB_vertex_shader &&
458                 RAS_EXT_support._ARB_shader_objects 
459                 )
460         {       
461                 float value[3];
462                 vec.getValue(value);
463                 bgl::blUniform3fvARB(uniform, 1, value);
464         }
465 #endif
466 }
467
468 void BL_Shader::SetUniform(int uniform, const MT_Tuple4& vec)
469 {
470 #ifdef GL_ARB_shader_objects
471         if( RAS_EXT_support._ARB_fragment_shader &&
472                 RAS_EXT_support._ARB_vertex_shader &&
473                 RAS_EXT_support._ARB_shader_objects 
474                 )
475         {
476                 float value[4];
477                 vec.getValue(value);
478                 bgl::blUniform4fvARB(uniform, 1, value);
479         }
480 #endif
481 }
482
483 void BL_Shader::SetUniform(int uniform, const unsigned int& val)
484 {
485 #ifdef GL_ARB_shader_objects
486         if( RAS_EXT_support._ARB_fragment_shader &&
487                 RAS_EXT_support._ARB_vertex_shader &&
488                 RAS_EXT_support._ARB_shader_objects 
489                 )
490         {
491                 bgl::blUniform1iARB(uniform, val);
492         }
493 #endif
494 }
495
496 void BL_Shader::SetUniform(int uniform, const float& val)
497 {
498 #ifdef GL_ARB_shader_objects
499         if( RAS_EXT_support._ARB_fragment_shader &&
500                 RAS_EXT_support._ARB_vertex_shader &&
501                 RAS_EXT_support._ARB_shader_objects 
502                 )
503         {
504                 bgl::blUniform1fARB(uniform, val);
505         }
506 #endif
507 }
508
509 void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose)
510 {
511 #ifdef GL_ARB_shader_objects
512         if( RAS_EXT_support._ARB_fragment_shader &&
513                 RAS_EXT_support._ARB_vertex_shader &&
514                 RAS_EXT_support._ARB_shader_objects 
515                 )
516         {
517                 float value[16];
518                 vec.getValue(value);
519                 bgl::blUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
520         }
521 #endif
522 }
523
524 void BL_Shader::SetUniform(int uniform, const MT_Matrix3x3& vec, bool transpose)
525 {
526 #ifdef GL_ARB_shader_objects
527         if( RAS_EXT_support._ARB_fragment_shader &&
528                 RAS_EXT_support._ARB_vertex_shader &&
529                 RAS_EXT_support._ARB_shader_objects 
530                 )
531         {
532                 float value[9];
533                 value[0] = vec[0][0]; value[1] = vec[1][0]; value[2] = vec[2][0]; 
534                 value[3] = vec[0][1]; value[4] = vec[1][1]; value[5] = vec[2][1]; 
535                 value[6] = vec[0][2]; value[7] = vec[1][2]; value[7] = vec[2][2]; 
536                 bgl::blUniformMatrix3fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
537         }
538 #endif
539 }
540
541 PyObject* BL_Shader::_getattr(const STR_String& attr)
542 {
543         _getattr_up(PyObjectPlus);
544 }
545
546
547 PyMethodDef BL_Shader::Methods[] = 
548 {
549         // creation
550         KX_PYMETHODTABLE( BL_Shader, setSource ),
551         KX_PYMETHODTABLE( BL_Shader, delSource ),
552         KX_PYMETHODTABLE( BL_Shader, getVertexProg ),
553         KX_PYMETHODTABLE( BL_Shader, getFragmentProg ),
554         KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ),
555         KX_PYMETHODTABLE( BL_Shader, validate),
556         /// access functions
557         KX_PYMETHODTABLE( BL_Shader, isValid),
558         KX_PYMETHODTABLE( BL_Shader, setUniform1f ),
559         KX_PYMETHODTABLE( BL_Shader, setUniform2f ),
560         KX_PYMETHODTABLE( BL_Shader, setUniform3f ),
561         KX_PYMETHODTABLE( BL_Shader, setUniform4f ),
562         KX_PYMETHODTABLE( BL_Shader, setUniform1i ),
563         KX_PYMETHODTABLE( BL_Shader, setUniform2i ),
564         KX_PYMETHODTABLE( BL_Shader, setUniform3i ),
565         KX_PYMETHODTABLE( BL_Shader, setUniform4i ),
566         KX_PYMETHODTABLE( BL_Shader, setAttrib ),
567
568         KX_PYMETHODTABLE( BL_Shader, setUniformfv ),
569         KX_PYMETHODTABLE( BL_Shader, setUniformiv ),
570         KX_PYMETHODTABLE( BL_Shader, setUniformDef ),
571
572         KX_PYMETHODTABLE( BL_Shader, setSampler  ),
573         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ),
574         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ),
575
576         {NULL,NULL} //Sentinel
577 };
578
579
580 PyTypeObject BL_Shader::Type = {
581         PyObject_HEAD_INIT(&PyType_Type)
582                 0,
583                 "BL_Shader",
584                 sizeof(BL_Shader),
585                 0,
586                 PyDestructor,
587                 0,
588                 __getattr,
589                 __setattr,
590                 0,
591                 __repr,
592                 0
593 };
594
595
596 PyParentObject BL_Shader::Parents[] = {
597         &PyObjectPlus::Type,
598         &BL_Shader::Type,
599         NULL
600 };
601
602
603 KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" )
604 {
605 #ifdef GL_ARB_shader_objects
606         if(mShader !=0 && mOk  )
607         {
608                 // already set...
609                 Py_Return;
610         }
611         char *v,*f;
612         int apply=0;
613         if( PyArg_ParseTuple(args, "ssi", &v, &f, &apply) )
614         {
615                 vertProg = v;
616                 fragProg = f;
617                 if( LinkProgram() ) {
618                         bgl::blUseProgramObjectARB( mShader );
619                         mUse = apply!=0;
620                         Py_Return;
621                 }
622                 vertProg = 0;
623                 fragProg = 0;
624                 mUse = 0;
625                 Py_Return;
626         }
627         return NULL;
628 #else
629         Py_Return;
630 #endif
631 }
632
633
634 KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" )
635 {
636 #ifdef GL_ARB_shader_objects
637         bgl::blDeleteObjectARB(mShader);
638         mShader         = 0;
639         vertProg        = 0;
640         fragProg        = 0;
641         mOk                     = 0;
642         mUse            = 0;
643         bgl::blUseProgramObjectARB(0);
644 #endif
645         Py_Return;
646
647 }
648
649 KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" )
650 {
651         return PyInt_FromLong( ( mShader !=0 &&  mOk ) );
652 }
653
654 KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" )
655 {
656         return PyString_FromString(vertProg?vertProg:"");
657 }
658
659 KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" )
660 {
661         return PyString_FromString(fragProg?fragProg:"");
662 }
663
664 KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()")
665 {
666 #ifdef GL_ARB_shader_objects
667         if(mError) {
668                 Py_INCREF(Py_None);
669                 return Py_None;
670         }
671         if(mShader==0) {
672                 PyErr_Format(PyExc_TypeError, "invalid shader object");
673                 return NULL;
674         }
675         int stat = 0;
676         bgl::blValidateProgramARB(mShader);
677         bgl::blGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB, &stat);
678
679         if(stat > 0) {
680                 int char_len=0;
681                 STR_String str("",stat);
682                 bgl::blGetInfoLogARB(mShader, stat, &char_len, str.Ptr());
683                 if(char_len >0) {
684                         spit("---- GLSL Validation ----");
685                         spit(str.ReadPtr());
686                 }
687                 str.Clear();
688         }
689 #endif//GL_ARB_shader_objects
690         Py_Return;
691 }
692
693
694 KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
695 {
696 #ifdef GL_ARB_shader_objects
697         if(mError) {
698                 Py_INCREF(Py_None);
699                 return Py_None;
700         }
701
702         char *uniform="";
703         int index=-1;
704         if(PyArg_ParseTuple(args, "si", &uniform, &index)) 
705         {
706                 if(mShader==0) {
707                         PyErr_Format(PyExc_ValueError, "invalid shader object");
708                         return NULL;
709                 }
710
711                 int loc= bgl::blGetUniformLocationARB(mShader, uniform);
712                 if( loc==-1 ) {
713                         spit("Invalid uniform value: " << uniform << ".");
714                         Py_Return;
715                 }
716
717                 else {
718                         if(index <= MAXTEX)
719                                 mSampler[index].loc = loc;
720                         else
721                                 spit("Invalid texture sample index: " << index);
722                         Py_Return;
723                 }
724         }
725         return NULL;
726 #else
727         Py_Return;
728 #endif//GL_ARB_shader_objects
729 }
730
731 KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" )
732 {
733         int pass = 1;
734         if(!PyArg_ParseTuple(args, "i", &pass))
735                 return NULL;
736
737         mPass = 1;
738         Py_Return;
739 }
740
741 /// access functions
742 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
743 {
744 #ifdef GL_ARB_shader_objects
745         if(mError) {
746                 Py_INCREF(Py_None);
747                 return Py_None;
748         }
749
750         char *uniform="";
751         float value=0;
752         if(PyArg_ParseTuple(args, "sf", &uniform, &value ))
753         {
754                 if( mShader==0 )
755                 {
756                         PyErr_Format(PyExc_ValueError, "invalid shader object");
757                         return NULL;
758                 }
759                 int loc= bgl::blGetUniformLocationARB(mShader, uniform);
760                 if( loc==-1 )
761                 {
762                         spit("Invalid uniform value: " << uniform << ".");
763                         Py_Return;
764                 }else
765                 {
766                         bgl::blUseProgramObjectARB( mShader );
767                         bgl::blUniform1fARB( loc, value );
768                         Py_Return;
769                 }
770
771         }
772         return NULL;
773 #else
774         Py_Return;
775 #endif
776 }
777
778
779 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
780 {
781 #ifdef GL_ARB_shader_objects
782         if(mError) {
783                 Py_INCREF(Py_None);
784                 return Py_None;
785         }
786         char *uniform="";
787         float array[2]={ 0,0 };
788         if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] ))
789         {
790                 if( mShader==0 )
791                 {
792                         PyErr_Format(PyExc_ValueError, "invalid shader object");
793                         return NULL;
794                 }
795                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
796                 if( loc==-1 )
797                 {
798                         spit("Invalid uniform value: " << uniform << ".");
799                         Py_Return;
800                 }else
801                 {
802                         bgl::blUseProgramObjectARB( mShader );
803                         bgl::blUniform2fARB(loc, array[0],array[1] );
804                         Py_Return;
805                 }
806
807         }
808         return NULL;
809 #else
810         Py_Return;
811 #endif//GL_ARB_shader_objects
812 }
813
814
815 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
816 {
817 #ifdef GL_ARB_shader_objects
818         if(mError) {
819                 Py_INCREF(Py_None);
820                 return Py_None;
821         }
822         char *uniform="";
823         float array[3]={0,0,0};
824         if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2]))
825         {
826                 if(mShader==0)
827                 {
828                         PyErr_Format(PyExc_ValueError, "invalid shader object");
829                         return NULL;
830                 }
831                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
832                 if( loc==-1 )
833                 {
834                         spit("Invalid uniform value: " << uniform << ".");
835                         Py_Return;
836                 }else
837                 {
838                         bgl::blUseProgramObjectARB(mShader);
839                         bgl::blUniform3fARB(loc, array[0],array[1],array[2]);
840                         Py_Return;
841                 }
842
843         }
844         return NULL;
845 #else
846         Py_Return;
847 #endif//GL_ARB_shader_objects
848 }
849
850
851 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
852 {
853 #ifdef GL_ARB_shader_objects
854         if(mError) {
855                 Py_INCREF(Py_None);
856                 return Py_None;
857         }
858         char *uniform="";
859         float array[4]={0,0,0,0};
860         if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3]))
861         {
862                 if(mShader==0)
863                 {
864                         PyErr_Format(PyExc_ValueError, "invalid shader object");
865                         return NULL;
866                 }
867                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
868                 if( loc==-1 )
869                 {
870                         spit("Invalid uniform value: " << uniform << ".");
871                         Py_Return;
872                 }else
873                 {
874                         bgl::blUseProgramObjectARB(mShader);
875                         bgl::blUniform4fARB(loc, array[0],array[1],array[2], array[3]);
876                         Py_Return;
877                 }
878         }
879         return NULL;
880 #else
881         Py_Return;
882 #endif//GL_ARB_shader_objects
883 }
884
885
886 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
887 {
888 #ifdef GL_ARB_shader_objects
889         if(mError) {
890                 Py_INCREF(Py_None);
891                 return Py_None;
892         }
893         char *uniform="";
894         int value=0;
895         if(PyArg_ParseTuple(args, "si", &uniform, &value ))
896         {
897                 if( mShader==0 )
898                 {
899                         PyErr_Format(PyExc_ValueError, "invalid shader object");
900                         return NULL;
901                 }
902                 int loc= bgl::blGetUniformLocationARB(mShader, uniform);
903                 if( loc==-1 )
904                 {
905                         spit("Invalid uniform value: " << uniform << ".");
906                         Py_Return;
907                 }else
908                 {
909                         bgl::blUseProgramObjectARB( mShader );
910                         bgl::blUniform1iARB( loc, value );
911                         Py_Return;
912                 }
913         }
914         return NULL;
915 #else
916         Py_Return;
917 #endif//GL_ARB_shader_objects
918 }
919
920
921 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
922 {
923 #ifdef GL_ARB_shader_objects
924         if(mError) {
925                 Py_INCREF(Py_None);
926                 return Py_None;
927         }
928         char *uniform="";
929         int array[2]={ 0,0 };
930         if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] ))
931         {
932                 if( mShader==0 )
933                 {
934                         PyErr_Format(PyExc_ValueError, "invalid shader object");
935                         return NULL;
936                 }
937                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
938                 if( loc==-1 )
939                 {
940                         spit("Invalid uniform value: " << uniform << ".");
941                         Py_Return;
942                 }else
943                 {
944                         bgl::blUseProgramObjectARB( mShader );
945                         bgl::blUniform2iARB(loc, array[0],array[1] );
946                         Py_Return;
947                 }
948         }
949         return NULL;
950 #else
951         Py_Return;
952 #endif//GL_ARB_shader_objects
953 }
954
955
956 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
957 {
958 #ifdef GL_ARB_shader_objects
959         if(mError) {
960                 Py_INCREF(Py_None);
961                 return Py_None;
962         }
963         char *uniform="";
964         int array[3]={0,0,0};
965         if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2]))
966         {
967                 if(mShader==0)
968                 {
969                         PyErr_Format(PyExc_ValueError, "invalid shader object");
970                         return NULL;
971                 }
972                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
973                 if( loc==-1 )
974                 {
975                         spit("Invalid uniform value: " << uniform << ".");
976                         Py_Return;
977                 }else
978                 {
979                         bgl::blUseProgramObjectARB(mShader);
980                         bgl::blUniform3iARB(loc, array[0],array[1],array[2]);
981                         Py_Return;
982                 }
983         }
984         return NULL;
985 #else
986         Py_Return;
987 #endif//GL_ARB_shader_objects
988 }
989
990 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
991 {
992 #ifdef GL_ARB_shader_objects
993         if(mError) {
994                 Py_INCREF(Py_None);
995                 return Py_None;
996         }
997         char *uniform="";
998         int array[4]={0,0,0, 0};
999         if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] ))
1000         {
1001                 if(mShader==0)
1002                 {
1003                         PyErr_Format(PyExc_ValueError, "invalid shader object");
1004                         return NULL;
1005                 }
1006                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
1007                 if( loc==-1 )
1008                 {
1009                         spit("Invalid uniform value: " << uniform << ".");
1010                         Py_Return;
1011                 }else
1012                 {
1013                         bgl::blUseProgramObjectARB(mShader);
1014                         bgl::blUniform4iARB(loc, array[0],array[1],array[2], array[3]);
1015                         Py_Return;
1016                 }
1017         }
1018         return NULL;
1019 #else
1020         Py_Return;
1021 #endif//GL_ARB_shader_objects
1022 }
1023
1024 KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )")
1025 {
1026 #ifdef GL_ARB_shader_objects
1027         if(mError) {
1028                 Py_INCREF(Py_None);
1029                 return Py_None;
1030         }
1031         char*uniform = "";
1032         PyObject *listPtr =0;
1033         float array_data[4] = {0.f,0.f,0.f,0.f};
1034
1035         if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
1036         {
1037                 if(mShader==0)
1038                 {
1039                         PyErr_Format(PyExc_ValueError, "invalid shader object");
1040                         return NULL;
1041                 }
1042                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
1043                 if( loc==-1 )
1044                 {
1045                         spit("Invalid uniform value: " << uniform << ".");
1046                         Py_Return;
1047                 }else
1048                 {
1049                         if(PySequence_Check(listPtr))
1050                         {
1051                                 unsigned int list_size = PySequence_Size(listPtr);
1052                                 
1053                                 for(unsigned int i=0; (i<list_size && i<=4); i++)
1054                                 {
1055                                         PyObject *item = PySequence_GetItem(listPtr, i);
1056                                         array_data[i] = (float)PyFloat_AsDouble(item);
1057                                         Py_DECREF(item);
1058                                 }
1059                                 switch(list_size)
1060                                 {
1061                                 case 2:
1062                                         {
1063                                                 bgl::blUseProgramObjectARB(mShader);
1064                                                 bgl::blUniform2fARB(loc, array_data[0],array_data[1]);
1065                                                 Py_Return;
1066                                         } break;
1067                                 case 3:
1068                                         {
1069                                                 bgl::blUseProgramObjectARB(mShader);
1070                                                 bgl::blUniform3fARB(loc, array_data[0],array_data[1], array_data[2]);
1071                                                 Py_Return;
1072                                         }break;
1073                                 case 4:
1074                                         {
1075                                                 bgl::blUseProgramObjectARB(mShader);
1076                                                 bgl::blUniform4fARB(loc, array_data[0],array_data[1], array_data[2], array_data[3]);
1077                                                 Py_Return;
1078                                         }break;
1079                                 default:
1080                                         {
1081                                                 PyErr_Format(PyExc_TypeError, "Invalid list size");
1082                                                 return NULL;
1083                                         }break;
1084                                 }
1085                         }
1086                 }
1087         }
1088         return NULL;
1089 #else
1090         Py_Return;
1091 #endif//GL_ARB_shader_objects
1092
1093 }
1094
1095 KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 or list4) )")
1096 {
1097 #ifdef GL_ARB_shader_objects
1098         if(mError) {
1099                 Py_INCREF(Py_None);
1100                 return Py_None;
1101         }
1102         char*uniform = "";
1103         PyObject *listPtr =0;
1104         int array_data[4] = {0,0,0,0};
1105
1106         if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
1107         {
1108                 if(mShader==0)
1109                 {
1110                         PyErr_Format(PyExc_ValueError, "invalid shader object");
1111                         return NULL;
1112                 }
1113                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
1114                 if( loc==-1 )
1115                 {
1116                         spit("Invalid uniform value: " << uniform << ".");
1117                         Py_Return;
1118                 }else
1119                 {
1120                         if(PySequence_Check(listPtr))
1121                         {
1122                                 unsigned int list_size = PySequence_Size(listPtr);
1123                                 
1124                                 for(unsigned int i=0; (i<list_size && i<=4); i++)
1125                                 {
1126                                         PyObject *item = PySequence_GetItem(listPtr, i);
1127                                         array_data[i] = PyInt_AsLong(item);
1128                                         Py_DECREF(item);
1129                                 }
1130                                 switch(list_size)
1131                                 {
1132                                 case 2:
1133                                         {
1134                                                 bgl::blUseProgramObjectARB(mShader);
1135                                                 bgl::blUniform2iARB(loc, array_data[0],array_data[1]);
1136                                                 Py_Return;
1137                                         } break;
1138                                 case 3:
1139                                         {
1140                                                 bgl::blUseProgramObjectARB(mShader);
1141                                                 bgl::blUniform3iARB(loc, array_data[0],array_data[1], array_data[2]);
1142                                                 Py_Return;
1143                                         }break;
1144                                 case 4:
1145                                         {
1146                                                 bgl::blUseProgramObjectARB(mShader);
1147                                                 bgl::blUniform4iARB(loc, array_data[0],array_data[1], array_data[2], array_data[3]);
1148                                                 Py_Return;
1149                                         }break;
1150                                 default:
1151                                         {
1152                                                 PyErr_Format(PyExc_TypeError, "Invalid list size");
1153                                                 return NULL;
1154                                         }break;
1155                                 }
1156                         }
1157                 }
1158         }
1159         return NULL;
1160 #else
1161         Py_Return;
1162 #endif//GL_ARB_shader_objects
1163 }
1164
1165
1166 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 
1167 "setUniformMatrix4(uniform-name, mat-4x4, transpose(row-major=true, col-major=false)" )
1168 {
1169 #ifdef GL_ARB_shader_objects
1170         if(mError) {
1171                 Py_INCREF(Py_None);
1172                 return Py_None;
1173         }
1174
1175         float matr[16] = {
1176                 1,0,0,0,
1177                 0,1,0,0,
1178                 0,0,1,0,
1179                 0,0,0,1
1180         };
1181
1182         char *uniform="";
1183         PyObject *matrix=0;
1184         int transp=1; // MT_ is row major so transpose by default....
1185         if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
1186         {
1187                 if(mShader==0)
1188                 {
1189                         PyErr_Format(PyExc_ValueError, "invalid shader object");
1190                         return NULL;
1191                 }
1192                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
1193                 if( loc==-1 )
1194                 {
1195                         spit("Invalid uniform value: " << uniform << ".");
1196                         Py_Return;
1197                 }else
1198                 {
1199                         if (PyObject_IsMT_Matrix(matrix, 4))
1200                         {
1201                                 MT_Matrix4x4 mat;
1202                                 if (PyMatTo(matrix, mat))
1203                                 {
1204                                         mat.getValue(matr);
1205                                         bgl::blUseProgramObjectARB(mShader);
1206                                         bgl::blUniformMatrix4fvARB(loc, 1, (transp!=0)?GL_TRUE:GL_FALSE, matr);
1207                                         Py_Return;
1208                                 }
1209                         }
1210                 }
1211         }
1212         return NULL;
1213 #else
1214         Py_Return;
1215 #endif//GL_ARB_shader_objects
1216 }
1217
1218
1219 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
1220 "setUniformMatrix3(uniform-name, list[3x3], transpose(row-major=true, col-major=false)" )
1221 {
1222 #ifdef GL_ARB_shader_objects
1223         if(mError) {
1224                 Py_INCREF(Py_None);
1225                 return Py_None;
1226         }
1227
1228         float matr[9] = {
1229                 1,0,0,
1230                 0,1,0,
1231                 0,0,1,
1232         };
1233
1234         char *uniform="";
1235         PyObject *matrix=0;
1236         int transp=1; // MT_ is row major so transpose by default....
1237         if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
1238         {
1239                 if(mShader==0)
1240                 {
1241                         PyErr_Format(PyExc_ValueError, "invalid shader object");
1242                         return NULL;
1243                 }
1244                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
1245                 if( loc==-1 )
1246                 {
1247                         spit("Invalid uniform value: " << uniform << ".");
1248                         Py_Return;
1249                 }else
1250                 {
1251                         if (PyObject_IsMT_Matrix(matrix, 3))
1252                         {
1253                                 MT_Matrix3x3 mat;
1254                                 if (PyMatTo(matrix, mat))
1255                                 {
1256                                         mat.getValue(matr);
1257                                         bgl::blUseProgramObjectARB(mShader);
1258                                         bgl::blUniformMatrix3fvARB(loc, 1, (transp!=0)?GL_TRUE:GL_FALSE, matr);
1259                                         Py_Return;
1260                                 }
1261                         }
1262                 }
1263         }
1264         return NULL;
1265 #else
1266         Py_Return;
1267 #endif//GL_ARB_shader_objects
1268 }
1269
1270 KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
1271 {
1272 #ifdef GL_ARB_shader_objects
1273         if(mError) {
1274                 Py_INCREF(Py_None);
1275                 return Py_None;
1276         }
1277         int attr=0;
1278         if(PyArg_ParseTuple(args, "i", &attr ))
1279         {
1280                 if(mShader==0)
1281                 {
1282                         PyErr_Format(PyExc_ValueError, "invalid shader object");
1283                         return NULL;
1284                 }
1285                 mAttr=SHD_TANGENT;
1286                 bgl::blUseProgramObjectARB(mShader);
1287                 bgl::blBindAttribLocationARB(mShader, mAttr, "Tangent");
1288                 Py_Return;
1289         }
1290         return NULL;
1291 #endif
1292         Py_Return;
1293 }
1294
1295 KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
1296 {
1297 #ifdef GL_ARB_shader_objects
1298         if(mError) {
1299                 Py_INCREF(Py_None);
1300                 return Py_None;
1301         }
1302
1303         char *uniform="";
1304         int nloc;
1305         if(PyArg_ParseTuple(args, "si",&uniform, &nloc))
1306         {
1307                 if(mShader==0) {
1308                         PyErr_Format(PyExc_ValueError, "invalid shader object");
1309                         return NULL;
1310                 }
1311                 int loc= bgl::blGetUniformLocationARB(mShader , uniform);
1312                 if( loc==-1 )
1313                 {
1314                         spit("Invalid uniform value: " << uniform << ".");
1315                         Py_Return;
1316                 }else
1317                 {
1318                         mPreDefLoc = loc;
1319                         mPreDefType = nloc;
1320                         Py_Return;
1321                 }
1322         }
1323         return NULL;
1324
1325 #endif
1326 }
1327
1328