Merge from trunk 16122-16307
[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_RETURN_NONE;
850         }
851         if(mShader==0) {
852                 PyErr_Format(PyExc_TypeError, "invalid shader object");
853                 return NULL;
854         }
855         int stat = 0;
856         glValidateProgramARB(mShader);
857         glGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB,(GLint*) &stat);
858
859
860         if(stat > 0 && stat < MAX_LOG_LEN) {
861                 int char_len=0;
862                 char *logInf = (char*)MEM_mallocN(stat, "validate-log");
863
864                 glGetInfoLogARB(mShader, stat,(GLsizei*) &char_len, logInf);
865                 if(char_len >0) {
866                         spit("---- GLSL Validation ----");
867                         spit(logInf);
868                 }
869                 MEM_freeN(logInf);
870                 logInf=0;
871         }
872         Py_Return;
873 }
874
875
876 KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
877 {
878         if(mError) {
879                 Py_RETURN_NONE;
880         }
881
882         char *uniform="";
883         int index=-1;
884         if(PyArg_ParseTuple(args, "si", &uniform, &index)) 
885         {
886                 int loc = GetUniformLocation(uniform);
887                 if(loc != -1) {
888                         if(index >= MAXTEX &&  index < 0)
889                                 spit("Invalid texture sample index: " << index);
890
891 #ifdef SORT_UNIFORMS
892                         SetUniformiv(loc, BL_Uniform::UNI_INT, &index, (sizeof(int)) );
893 #else
894                         SetUniform(loc, index);
895 #endif
896                         //if(index <= MAXTEX)
897                         //      mSampler[index].mLoc = loc;
898                         //else
899                         //      spit("Invalid texture sample index: " << index);
900                 }
901                 Py_RETURN_NONE;
902         }
903         return NULL;
904 }
905
906 KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" )
907 {
908         int pass = 1;
909         if(!PyArg_ParseTuple(args, "i", &pass))
910                 return NULL;
911
912         mPass = 1;
913         Py_Return;
914 }
915
916 /// access functions
917 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
918 {
919         if(mError) {
920                 Py_RETURN_NONE;
921         }
922
923         char *uniform="";
924         float value=0;
925         if(PyArg_ParseTuple(args, "sf", &uniform, &value ))
926         {
927                 int loc = GetUniformLocation(uniform);
928                 if(loc != -1)
929                 {
930 #ifdef SORT_UNIFORMS
931                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT, &value, sizeof(float));
932 #else                   
933                         SetUniform( loc, (float)value );
934 #endif
935                 }
936                 Py_Return;
937         }
938         return NULL;
939 }
940
941
942 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
943 {
944         if(mError) {
945                 Py_RETURN_NONE;
946         }
947         char *uniform="";
948         float array[2]={ 0,0 };
949         if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] ))
950         {
951                 int loc = GetUniformLocation(uniform);
952                 if(loc != -1)
953                 {
954 #ifdef SORT_UNIFORMS
955                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array, (sizeof(float)*2) );
956 #else
957                         SetUniform(loc, array, 2);
958 #endif
959                 }
960                 Py_Return;
961         }
962         return NULL;
963 }
964
965
966 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
967 {
968         if(mError) {
969                 Py_RETURN_NONE;
970         }
971         char *uniform="";
972         float array[3]={0,0,0};
973         if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2]))
974         {
975                 int loc = GetUniformLocation(uniform);
976                 if(loc != -1)
977                 {
978 #ifdef SORT_UNIFORMS
979                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array, (sizeof(float)*3) );
980 #else
981                         SetUniform(loc, array, 3);
982 #endif
983                 }
984                 Py_Return;
985
986         }
987         return NULL;
988 }
989
990
991 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
992 {
993         if(mError) {
994                 Py_RETURN_NONE;
995         }
996         char *uniform="";
997         float array[4]={0,0,0,0};
998         if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3]))
999         {
1000                 int loc = GetUniformLocation(uniform);
1001                 if(loc != -1)
1002                 {
1003 #ifdef SORT_UNIFORMS
1004                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array, (sizeof(float)*4) );
1005 #else
1006                         SetUniform(loc, array, 4);
1007 #endif
1008                 }
1009                 Py_Return;
1010         }
1011         return NULL;
1012 }
1013
1014
1015 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
1016 {
1017         if(mError) {
1018                 Py_RETURN_NONE;
1019         }
1020         char *uniform="";
1021         int value=0;
1022         if(PyArg_ParseTuple(args, "si", &uniform, &value ))
1023         {
1024                 int loc = GetUniformLocation(uniform);
1025                 if(loc != -1)
1026                 {
1027 #ifdef SORT_UNIFORMS
1028                         SetUniformiv(loc, BL_Uniform::UNI_INT, &value, sizeof(int));
1029 #else
1030                         SetUniform(loc, (int)value);
1031 #endif
1032                 }
1033                 Py_Return;
1034         }
1035         return NULL;
1036 }
1037
1038
1039 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
1040 {
1041         if(mError) {
1042                 Py_RETURN_NONE;
1043         }
1044         char *uniform="";
1045         int array[2]={ 0,0 };
1046         if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] ))
1047         {
1048                 int loc = GetUniformLocation(uniform);
1049                 if(loc != -1)
1050                 {
1051 #ifdef SORT_UNIFORMS
1052                         SetUniformiv(loc, BL_Uniform::UNI_INT2, array, sizeof(int)*2);
1053 #else
1054                         SetUniform(loc, array, 2);
1055 #endif
1056                 }
1057                 Py_Return;
1058         }
1059         return NULL;
1060 }
1061
1062
1063 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
1064 {
1065         if(mError) {
1066                 Py_RETURN_NONE;
1067         }
1068
1069         char *uniform="";
1070         int array[3]={0,0,0};
1071         if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2]))
1072         {
1073                 int loc = GetUniformLocation(uniform);
1074                 if(loc != -1)
1075                 {
1076 #ifdef SORT_UNIFORMS
1077                         SetUniformiv(loc, BL_Uniform::UNI_INT3, array, sizeof(int)*3);
1078 #else
1079                         SetUniform(loc, array, 3);
1080 #endif
1081                 }
1082                 Py_Return;
1083         }
1084         return NULL;
1085 }
1086
1087 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
1088 {
1089         if(mError) {
1090                 Py_RETURN_NONE;
1091         }
1092         char *uniform="";
1093         int array[4]={0,0,0, 0};
1094         if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] ))
1095         {
1096                 int loc = GetUniformLocation(uniform);
1097                 if(loc != -1)
1098                 {
1099 #ifdef SORT_UNIFORMS
1100                         SetUniformiv(loc, BL_Uniform::UNI_INT4, array, sizeof(int)*4);
1101 #else
1102                         SetUniform(loc, array, 4);
1103 #endif
1104                 }
1105                 Py_Return;
1106         }
1107         return NULL;
1108 }
1109
1110 KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )")
1111 {
1112         if(mError) {
1113                 Py_RETURN_NONE;
1114         }
1115         char*uniform = "";
1116         PyObject *listPtr =0;
1117         float array_data[4] = {0.f,0.f,0.f,0.f};
1118
1119         if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
1120         {
1121                 int loc = GetUniformLocation(uniform);
1122                 if(loc != -1)
1123                 {
1124                         if(PySequence_Check(listPtr))
1125                         {
1126                                 unsigned int list_size = PySequence_Size(listPtr);
1127                                 
1128                                 for(unsigned int i=0; (i<list_size && i<4); i++)
1129                                 {
1130                                         PyObject *item = PySequence_GetItem(listPtr, i);
1131                                         array_data[i] = (float)PyFloat_AsDouble(item);
1132                                         Py_DECREF(item);
1133                                 }
1134
1135                                 switch(list_size)
1136                                 {
1137                                 case 2:
1138                                         {
1139                                                 float array2[2] = { array_data[0],array_data[1] };
1140 #ifdef SORT_UNIFORMS
1141                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array2, sizeof(float)*2);
1142 #else
1143                                                 SetUniform(loc, array2, 2);                                             
1144 #endif
1145                                                 Py_Return;
1146                                         } break;
1147                                 case 3:
1148                                         {
1149                                                 float array3[3] = { array_data[0],array_data[1],array_data[2] };
1150 #ifdef SORT_UNIFORMS
1151                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array3, sizeof(float)*3);
1152 #else
1153                                                 SetUniform(loc, array3, 3);     
1154 #endif
1155                                                 Py_Return;
1156                                         }break;
1157                                 case 4:
1158                                         {
1159                                                 float array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
1160 #ifdef SORT_UNIFORMS
1161                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array4, sizeof(float)*4);
1162 #else
1163                                                 SetUniform(loc, array4, 4);     
1164 #endif
1165                                                 Py_Return;
1166                                         }break;
1167                                 default:
1168                                         {
1169                                                 PyErr_Format(PyExc_TypeError, "Invalid list size");
1170                                                 return NULL;
1171                                         }break;
1172                                 }
1173                         }
1174                 }
1175         }
1176         return NULL;
1177 }
1178
1179 KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 or list4) )")
1180 {
1181         if(mError) {
1182                 Py_RETURN_NONE;
1183         }
1184         char*uniform = "";
1185         PyObject *listPtr =0;
1186         int array_data[4] = {0,0,0,0};
1187
1188         if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
1189         {
1190                 int loc = GetUniformLocation(uniform);
1191                 if(loc != -1)
1192                 {
1193                         if(PySequence_Check(listPtr))
1194                         {
1195                                 unsigned int list_size = PySequence_Size(listPtr);
1196                                 
1197                                 for(unsigned int i=0; (i<list_size && i<4); i++)
1198                                 {
1199                                         PyObject *item = PySequence_GetItem(listPtr, i);
1200                                         array_data[i] = PyInt_AsLong(item);
1201                                         Py_DECREF(item);
1202                                 }
1203                                 switch(list_size)
1204                                 {
1205                                 case 2:
1206                                         {
1207                                                 int array2[2] = { array_data[0],array_data[1]};
1208 #ifdef SORT_UNIFORMS
1209                                                 SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
1210 #else
1211                                                 SetUniform(loc, array2, 2);                                             
1212 #endif
1213                                                 Py_Return;
1214                                         } break;
1215                                 case 3:
1216                                         {
1217                                                 int array3[3] = { array_data[0],array_data[1],array_data[2] };
1218 #ifdef SORT_UNIFORMS
1219                                                 SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
1220                                                 
1221 #else
1222                                                 SetUniform(loc, array3, 3);     
1223 #endif
1224                                                 Py_Return;
1225                                         }break;
1226                                 case 4:
1227                                         {
1228                                                 int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
1229 #ifdef SORT_UNIFORMS
1230                                                 SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
1231                                                 
1232 #else
1233                                                 SetUniform(loc, array4, 4);     
1234 #endif
1235                                                 Py_Return;
1236                                         }break;
1237                                 default:
1238                                         {
1239                                                 PyErr_Format(PyExc_TypeError, "Invalid list size");
1240                                                 return NULL;
1241                                         }break;
1242                                 }
1243                         }
1244                 }
1245         }
1246         return NULL;
1247 }
1248
1249
1250 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 
1251 "setUniformMatrix4(uniform-name, mat-4x4, transpose(row-major=true, col-major=false)" )
1252 {
1253         if(mError) {
1254                 Py_RETURN_NONE;
1255         }
1256
1257         float matr[16] = {
1258                 1,0,0,0,
1259                 0,1,0,0,
1260                 0,0,1,0,
1261                 0,0,0,1
1262         };
1263
1264         char *uniform="";
1265         PyObject *matrix=0;
1266         int transp=1; // MT_ is row major so transpose by default....
1267         if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
1268         {
1269                 int loc = GetUniformLocation(uniform);
1270                 if(loc != -1)
1271                 {
1272                         if (PyObject_IsMT_Matrix(matrix, 4))
1273                         {
1274                                 MT_Matrix4x4 mat;
1275                                 if (PyMatTo(matrix, mat))
1276                                 {
1277 #ifdef SORT_UNIFORMS
1278                                         mat.getValue(matr);
1279                                         SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) );
1280 #else
1281                                         SetUniform(loc,mat,(transp!=0));
1282 #endif
1283                                         Py_Return;
1284                                 }
1285                         }
1286                 }
1287         }
1288         return NULL;
1289 }
1290
1291
1292 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
1293 "setUniformMatrix3(uniform-name, list[3x3], transpose(row-major=true, col-major=false)" )
1294 {
1295         if(mError) {
1296                 Py_RETURN_NONE;
1297         }
1298
1299         float matr[9] = {
1300                 1,0,0,
1301                 0,1,0,
1302                 0,0,1,
1303         };
1304
1305         char *uniform="";
1306         PyObject *matrix=0;
1307         int transp=1; // MT_ is row major so transpose by default....
1308         if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
1309         {
1310                 int loc = GetUniformLocation(uniform);
1311                 if(loc != -1)
1312                 {
1313                         if (PyObject_IsMT_Matrix(matrix, 3))
1314                         {
1315                                 MT_Matrix3x3 mat;
1316                                 if (PyMatTo(matrix, mat))
1317                                 {
1318 #ifdef SORT_UNIFORMS
1319                                         mat.getValue(matr);
1320                                         SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) );
1321 #else
1322                                         SetUniform(loc,mat,(transp!=0));
1323 #endif
1324                                         Py_Return;
1325
1326                                 }
1327                         }
1328                 }
1329         }
1330         return NULL;
1331 }
1332
1333 KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
1334 {
1335         if(mError) {
1336                 Py_RETURN_NONE;
1337         }
1338         int attr=0;
1339         if(PyArg_ParseTuple(args, "i", &attr )) {
1340                 if(mShader==0) {
1341                         PyErr_Format(PyExc_ValueError, "invalid shader object");
1342                         return NULL;
1343                 }
1344                 mAttr=SHD_TANGENT;
1345                 glUseProgramObjectARB(mShader);
1346                 glBindAttribLocationARB(mShader, mAttr, "Tangent");
1347                 Py_Return;
1348         }
1349         return NULL;
1350 }
1351
1352
1353 KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
1354 {
1355         if(mError) {
1356                 Py_RETURN_NONE;
1357         }
1358
1359         char *uniform="";
1360         int nloc=0;
1361         if(PyArg_ParseTuple(args, "si",&uniform, &nloc))
1362         {
1363                 int loc = GetUniformLocation(uniform);
1364                 if(loc != -1)
1365                 {
1366                         bool defined = false;
1367                         BL_UniformVecDef::iterator it = mPreDef.begin();
1368                         while(it != mPreDef.end()) {
1369                                 if((*it)->mLoc == loc) {
1370                                         defined = true;
1371                                         break;
1372                                 }
1373                                 it++;
1374                         }
1375                         if(defined)
1376                         {
1377                                 Py_Return;
1378                         }
1379
1380                         BL_DefUniform *uni = new BL_DefUniform();
1381                         uni->mLoc = loc;
1382                         uni->mType = nloc;
1383                         uni->mFlag = 0;
1384                         mPreDef.push_back(uni);
1385                         Py_Return;
1386                 }
1387         }
1388         return NULL;
1389 }
1390
1391 // eof