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