* removed typedefs that were not used (from anonymous enums and structs)
[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 RAS_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                 const MT_Matrix4x4& view = rasty->GetViewMatrix();
449
450                 if(mAttr==SHD_TANGENT)
451                          ms.m_mesh->SetMeshModified(true);
452
453                 BL_UniformVecDef::iterator it;
454                 for(it = mPreDef.begin(); it!= mPreDef.end(); it++)
455                 {
456                         BL_DefUniform *uni = (*it);
457                         if(uni->mLoc == -1) continue;
458
459                         switch (uni->mType)
460                         {
461                                 case MODELMATRIX:
462                                         {
463                                                 SetUniform(uni->mLoc, model);
464                                                 break;
465                                         }
466                                 case MODELMATRIX_TRANSPOSE:
467                                         {
468                                                 SetUniform(uni->mLoc, model, true);
469                                                 break;
470                                         }
471                                 case MODELMATRIX_INVERSE:
472                                         {
473                                                 model.invert();
474                                                 SetUniform(uni->mLoc, model);
475                                                 break;
476                                         }
477                                 case MODELMATRIX_INVERSETRANSPOSE:
478                                         {
479                                                 model.invert();
480                                                 SetUniform(uni->mLoc, model, true);
481                                                 break;
482                                         }
483                                 case MODELVIEWMATRIX:
484                                         {
485                                                 SetUniform(uni->mLoc, view*model);
486                                                 break;
487                                         }
488
489                                 case MODELVIEWMATRIX_TRANSPOSE:
490                                         {
491                                                 MT_Matrix4x4 mat(view*model);
492                                                 SetUniform(uni->mLoc, mat, true);
493                                                 break;
494                                         }
495                                 case MODELVIEWMATRIX_INVERSE:
496                                         {
497                                                 MT_Matrix4x4 mat(view*model);
498                                                 mat.invert();
499                                                 SetUniform(uni->mLoc, mat);
500                                                 break;
501                                         }
502                                 case MODELVIEWMATRIX_INVERSETRANSPOSE:
503                                         {
504                                                 MT_Matrix4x4 mat(view*model);
505                                                 mat.invert();
506                                                 SetUniform(uni->mLoc, mat, true);
507                                                 break;
508                                         }
509                                 case CAM_POS:
510                                         {
511                                                 MT_Point3 pos(rasty->GetCameraPosition());
512                                                 SetUniform(uni->mLoc, pos);
513                                                 break;
514                                         }
515                                 case VIEWMATRIX:
516                                         {
517                                                 SetUniform(uni->mLoc, view);
518                                                 break;
519                                         }
520                                 case VIEWMATRIX_TRANSPOSE:
521                                         {
522                                                 SetUniform(uni->mLoc, view, true);
523                                                 break;
524                                         }
525                                 case VIEWMATRIX_INVERSE:
526                                         {
527                                                 MT_Matrix4x4 viewinv = view;
528                                                 viewinv.invert();
529                                                 SetUniform(uni->mLoc, view);
530                                                 break;
531                                         }
532                                 case VIEWMATRIX_INVERSETRANSPOSE:
533                                         {
534                                                 MT_Matrix4x4 viewinv = view;
535                                                 viewinv.invert();
536                                                 SetUniform(uni->mLoc, view, true);
537                                                 break;
538                                         }
539                                 case CONSTANT_TIMER:
540                                         {
541                                                 SetUniform(uni->mLoc, (float)rasty->GetTime());
542                                                 break;
543                                         }
544                                 default:
545                                         break;
546                         }
547                 }
548         }
549 }
550
551
552 int BL_Shader::GetAttribLocation(const STR_String& name)
553 {
554         if( GLEW_ARB_fragment_shader &&
555                 GLEW_ARB_vertex_shader &&
556                 GLEW_ARB_shader_objects 
557                 )
558         {
559                 return glGetAttribLocationARB(mShader, name.ReadPtr());
560         }
561
562         return -1;
563 }
564
565 void BL_Shader::BindAttribute(const STR_String& attr, int loc)
566 {
567         if( GLEW_ARB_fragment_shader &&
568                 GLEW_ARB_vertex_shader &&
569                 GLEW_ARB_shader_objects 
570                 )
571         {
572                 glBindAttribLocationARB(mShader, loc, attr.ReadPtr());
573         }
574 }
575
576 int BL_Shader::GetUniformLocation(const STR_String& name)
577 {
578         if( GLEW_ARB_fragment_shader &&
579                 GLEW_ARB_vertex_shader &&
580                 GLEW_ARB_shader_objects 
581                 )
582         {
583                 MT_assert(mShader!=0);
584                 int location = glGetUniformLocationARB(mShader, name.ReadPtr());
585                 if(location == -1)
586                         spit("Invalid uniform value: " << name.ReadPtr() << ".");
587                 return location;
588         }
589
590         return -1;
591 }
592
593 void BL_Shader::SetUniform(int uniform, const MT_Tuple2& vec)
594 {
595         if( GLEW_ARB_fragment_shader &&
596                 GLEW_ARB_vertex_shader &&
597                 GLEW_ARB_shader_objects 
598                 )
599         {
600                 float value[2];
601                 vec.getValue(value);
602                 glUniform2fvARB(uniform, 1, value);
603         }
604
605 }
606
607 void BL_Shader::SetUniform(int uniform, const MT_Tuple3& vec)
608 {
609         if( GLEW_ARB_fragment_shader &&
610                 GLEW_ARB_vertex_shader &&
611                 GLEW_ARB_shader_objects 
612                 )
613         {       
614                 float value[3];
615                 vec.getValue(value);
616                 glUniform3fvARB(uniform, 1, value);
617         }
618 }
619
620 void BL_Shader::SetUniform(int uniform, const MT_Tuple4& vec)
621 {
622         if( GLEW_ARB_fragment_shader &&
623                 GLEW_ARB_vertex_shader &&
624                 GLEW_ARB_shader_objects 
625                 )
626         {
627                 float value[4];
628                 vec.getValue(value);
629                 glUniform4fvARB(uniform, 1, value);
630         }
631 }
632
633 void BL_Shader::SetUniform(int uniform, const unsigned int& val)
634 {
635         if( GLEW_ARB_fragment_shader &&
636                 GLEW_ARB_vertex_shader &&
637                 GLEW_ARB_shader_objects 
638                 )
639         {
640                 glUniform1iARB(uniform, val);
641         }
642 }
643
644 void BL_Shader::SetUniform(int uniform, const int val)
645 {
646         if( GLEW_ARB_fragment_shader &&
647                 GLEW_ARB_vertex_shader &&
648                 GLEW_ARB_shader_objects 
649                 )
650         {
651                 glUniform1iARB(uniform, val);
652         }
653 }
654
655 void BL_Shader::SetUniform(int uniform, const float& val)
656 {
657         if( GLEW_ARB_fragment_shader &&
658                 GLEW_ARB_vertex_shader &&
659                 GLEW_ARB_shader_objects 
660                 )
661         {
662                 glUniform1fARB(uniform, val);
663         }
664 }
665
666 void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose)
667 {
668         if( GLEW_ARB_fragment_shader &&
669                 GLEW_ARB_vertex_shader &&
670                 GLEW_ARB_shader_objects 
671                 )
672         {
673                 float value[16];
674                 // note: getValue gives back column major as needed by OpenGL
675                 vec.getValue(value);
676                 glUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
677         }
678 }
679
680 void BL_Shader::SetUniform(int uniform, const MT_Matrix3x3& vec, bool transpose)
681 {
682         if( GLEW_ARB_fragment_shader &&
683                 GLEW_ARB_vertex_shader &&
684                 GLEW_ARB_shader_objects 
685                 )
686         {
687                 float value[9];
688                 value[0] = (float)vec[0][0]; value[1] = (float)vec[1][0]; value[2] = (float)vec[2][0]; 
689                 value[3] = (float)vec[0][1]; value[4] = (float)vec[1][1]; value[5] = (float)vec[2][1]; 
690                 value[6] = (float)vec[0][2]; value[7] = (float)vec[1][2]; value[7] = (float)vec[2][2]; 
691                 glUniformMatrix3fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
692         }
693 }
694
695 void BL_Shader::SetUniform(int uniform, const float* val, int len)
696 {
697         if( GLEW_ARB_fragment_shader &&
698                 GLEW_ARB_vertex_shader &&
699                 GLEW_ARB_shader_objects 
700                 )
701         {
702                 if(len == 2) 
703                         glUniform2fvARB(uniform, 1,(GLfloat*)val);
704                 else if (len == 3)
705                         glUniform3fvARB(uniform, 1,(GLfloat*)val);
706                 else if (len == 4)
707                         glUniform4fvARB(uniform, 1,(GLfloat*)val);
708                 else
709                         MT_assert(0);
710         }
711 }
712
713 void BL_Shader::SetUniform(int uniform, const int* val, int len)
714 {
715         if( GLEW_ARB_fragment_shader &&
716                 GLEW_ARB_vertex_shader &&
717                 GLEW_ARB_shader_objects 
718                 )
719         {
720                 if(len == 2) 
721                         glUniform2ivARB(uniform, 1, (GLint*)val);
722                 else if (len == 3)
723                         glUniform3ivARB(uniform, 1, (GLint*)val);
724                 else if (len == 4)
725                         glUniform4ivARB(uniform, 1, (GLint*)val);
726                 else
727                         MT_assert(0);
728         }
729 }
730
731
732 PyObject* BL_Shader::_getattr(const char *attr)
733 {
734         _getattr_up(PyObjectPlus);
735 }
736
737
738 PyMethodDef BL_Shader::Methods[] = 
739 {
740         // creation
741         KX_PYMETHODTABLE( BL_Shader, setSource ),
742         KX_PYMETHODTABLE( BL_Shader, delSource ),
743         KX_PYMETHODTABLE( BL_Shader, getVertexProg ),
744         KX_PYMETHODTABLE( BL_Shader, getFragmentProg ),
745         KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ),
746         KX_PYMETHODTABLE( BL_Shader, validate),
747         /// access functions
748         KX_PYMETHODTABLE( BL_Shader, isValid),
749         KX_PYMETHODTABLE( BL_Shader, setUniform1f ),
750         KX_PYMETHODTABLE( BL_Shader, setUniform2f ),
751         KX_PYMETHODTABLE( BL_Shader, setUniform3f ),
752         KX_PYMETHODTABLE( BL_Shader, setUniform4f ),
753         KX_PYMETHODTABLE( BL_Shader, setUniform1i ),
754         KX_PYMETHODTABLE( BL_Shader, setUniform2i ),
755         KX_PYMETHODTABLE( BL_Shader, setUniform3i ),
756         KX_PYMETHODTABLE( BL_Shader, setUniform4i ),
757         KX_PYMETHODTABLE( BL_Shader, setAttrib ),
758
759         KX_PYMETHODTABLE( BL_Shader, setUniformfv ),
760         KX_PYMETHODTABLE( BL_Shader, setUniformiv ),
761         KX_PYMETHODTABLE( BL_Shader, setUniformDef ),
762
763         KX_PYMETHODTABLE( BL_Shader, setSampler  ),
764         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ),
765         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ),
766
767         {NULL,NULL} //Sentinel
768 };
769
770
771 PyTypeObject BL_Shader::Type = {
772         PyObject_HEAD_INIT(&PyType_Type)
773                 0,
774                 "BL_Shader",
775                 sizeof(BL_Shader),
776                 0,
777                 PyDestructor,
778                 0,
779                 __getattr,
780                 __setattr,
781                 0,
782                 __repr,
783                 0
784 };
785
786
787 PyParentObject BL_Shader::Parents[] = {
788         &PyObjectPlus::Type,
789         &BL_Shader::Type,
790         NULL
791 };
792
793
794 KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" )
795 {
796         if(mShader !=0 && mOk  )
797         {
798                 // already set...
799                 Py_RETURN_NONE;
800         }
801         char *v,*f;
802         int apply=0;
803         if( PyArg_ParseTuple(args, "ssi", &v, &f, &apply) )
804         {
805                 vertProg = v;
806                 fragProg = f;
807                 if( LinkProgram() ) {
808                         glUseProgramObjectARB( mShader );
809                         mUse = apply!=0;
810                         Py_RETURN_NONE;
811                 }
812                 vertProg = 0;
813                 fragProg = 0;
814                 mUse = 0;
815                 Py_RETURN_NONE;
816         }
817         return NULL;
818 }
819
820
821 KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" )
822 {
823         ClearUniforms();
824         glUseProgramObjectARB(0);
825
826         glDeleteObjectARB(mShader);
827         mShader         = 0;
828         mOk                     = 0;
829         mUse            = 0;
830         Py_RETURN_NONE;
831 }
832
833 KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" )
834 {
835         return PyInt_FromLong( ( mShader !=0 &&  mOk ) );
836 }
837
838 KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" )
839 {
840         return PyString_FromString(vertProg?vertProg:"");
841 }
842
843 KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" )
844 {
845         return PyString_FromString(fragProg?fragProg:"");
846 }
847
848 KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()")
849 {
850         if(mError) {
851                 Py_RETURN_NONE;
852         }
853         if(mShader==0) {
854                 PyErr_Format(PyExc_TypeError, "invalid shader object");
855                 return NULL;
856         }
857         int stat = 0;
858         glValidateProgramARB(mShader);
859         glGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB,(GLint*) &stat);
860
861
862         if(stat > 0 && stat < MAX_LOG_LEN) {
863                 int char_len=0;
864                 char *logInf = (char*)MEM_mallocN(stat, "validate-log");
865
866                 glGetInfoLogARB(mShader, stat,(GLsizei*) &char_len, logInf);
867                 if(char_len >0) {
868                         spit("---- GLSL Validation ----");
869                         spit(logInf);
870                 }
871                 MEM_freeN(logInf);
872                 logInf=0;
873         }
874         Py_RETURN_NONE;
875 }
876
877
878 KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
879 {
880         if(mError) {
881                 Py_RETURN_NONE;
882         }
883
884         const 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_NONE;
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_NONE;
916 }
917
918 /// access functions
919 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
920 {
921         if(mError) {
922                 Py_RETURN_NONE;
923         }
924
925         const char *uniform="";
926         float value=0;
927         if(PyArg_ParseTuple(args, "sf", &uniform, &value ))
928         {
929                 int loc = GetUniformLocation(uniform);
930                 if(loc != -1)
931                 {
932 #ifdef SORT_UNIFORMS
933                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT, &value, sizeof(float));
934 #else                   
935                         SetUniform( loc, (float)value );
936 #endif
937                 }
938                 Py_RETURN_NONE;
939         }
940         return NULL;
941 }
942
943
944 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
945 {
946         if(mError) {
947                 Py_RETURN_NONE;
948         }
949         const char *uniform="";
950         float array[2]={ 0,0 };
951         if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] ))
952         {
953                 int loc = GetUniformLocation(uniform);
954                 if(loc != -1)
955                 {
956 #ifdef SORT_UNIFORMS
957                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array, (sizeof(float)*2) );
958 #else
959                         SetUniform(loc, array, 2);
960 #endif
961                 }
962                 Py_RETURN_NONE;
963         }
964         return NULL;
965 }
966
967
968 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
969 {
970         if(mError) {
971                 Py_RETURN_NONE;
972         }
973         const char *uniform="";
974         float array[3]={0,0,0};
975         if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2]))
976         {
977                 int loc = GetUniformLocation(uniform);
978                 if(loc != -1)
979                 {
980 #ifdef SORT_UNIFORMS
981                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array, (sizeof(float)*3) );
982 #else
983                         SetUniform(loc, array, 3);
984 #endif
985                 }
986                 Py_RETURN_NONE;
987
988         }
989         return NULL;
990 }
991
992
993 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
994 {
995         if(mError) {
996                 Py_RETURN_NONE;
997         }
998         const char *uniform="";
999         float array[4]={0,0,0,0};
1000         if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3]))
1001         {
1002                 int loc = GetUniformLocation(uniform);
1003                 if(loc != -1)
1004                 {
1005 #ifdef SORT_UNIFORMS
1006                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array, (sizeof(float)*4) );
1007 #else
1008                         SetUniform(loc, array, 4);
1009 #endif
1010                 }
1011                 Py_RETURN_NONE;
1012         }
1013         return NULL;
1014 }
1015
1016
1017 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
1018 {
1019         if(mError) {
1020                 Py_RETURN_NONE;
1021         }
1022         const char *uniform="";
1023         int value=0;
1024         if(PyArg_ParseTuple(args, "si", &uniform, &value ))
1025         {
1026                 int loc = GetUniformLocation(uniform);
1027                 if(loc != -1)
1028                 {
1029 #ifdef SORT_UNIFORMS
1030                         SetUniformiv(loc, BL_Uniform::UNI_INT, &value, sizeof(int));
1031 #else
1032                         SetUniform(loc, (int)value);
1033 #endif
1034                 }
1035                 Py_RETURN_NONE;
1036         }
1037         return NULL;
1038 }
1039
1040
1041 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
1042 {
1043         if(mError) {
1044                 Py_RETURN_NONE;
1045         }
1046         const char *uniform="";
1047         int array[2]={ 0,0 };
1048         if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] ))
1049         {
1050                 int loc = GetUniformLocation(uniform);
1051                 if(loc != -1)
1052                 {
1053 #ifdef SORT_UNIFORMS
1054                         SetUniformiv(loc, BL_Uniform::UNI_INT2, array, sizeof(int)*2);
1055 #else
1056                         SetUniform(loc, array, 2);
1057 #endif
1058                 }
1059                 Py_RETURN_NONE;
1060         }
1061         return NULL;
1062 }
1063
1064
1065 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
1066 {
1067         if(mError) {
1068                 Py_RETURN_NONE;
1069         }
1070
1071         const char *uniform="";
1072         int array[3]={0,0,0};
1073         if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2]))
1074         {
1075                 int loc = GetUniformLocation(uniform);
1076                 if(loc != -1)
1077                 {
1078 #ifdef SORT_UNIFORMS
1079                         SetUniformiv(loc, BL_Uniform::UNI_INT3, array, sizeof(int)*3);
1080 #else
1081                         SetUniform(loc, array, 3);
1082 #endif
1083                 }
1084                 Py_RETURN_NONE;
1085         }
1086         return NULL;
1087 }
1088
1089 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
1090 {
1091         if(mError) {
1092                 Py_RETURN_NONE;
1093         }
1094         const char *uniform="";
1095         int array[4]={0,0,0, 0};
1096         if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] ))
1097         {
1098                 int loc = GetUniformLocation(uniform);
1099                 if(loc != -1)
1100                 {
1101 #ifdef SORT_UNIFORMS
1102                         SetUniformiv(loc, BL_Uniform::UNI_INT4, array, sizeof(int)*4);
1103 #else
1104                         SetUniform(loc, array, 4);
1105 #endif
1106                 }
1107                 Py_RETURN_NONE;
1108         }
1109         return NULL;
1110 }
1111
1112 KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )")
1113 {
1114         if(mError) {
1115                 Py_RETURN_NONE;
1116         }
1117         const char *uniform = "";
1118         PyObject *listPtr =0;
1119         float array_data[4] = {0.f,0.f,0.f,0.f};
1120
1121         if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
1122         {
1123                 int loc = GetUniformLocation(uniform);
1124                 if(loc != -1)
1125                 {
1126                         if(PySequence_Check(listPtr))
1127                         {
1128                                 unsigned int list_size = PySequence_Size(listPtr);
1129                                 
1130                                 for(unsigned int i=0; (i<list_size && i<4); i++)
1131                                 {
1132                                         PyObject *item = PySequence_GetItem(listPtr, i);
1133                                         array_data[i] = (float)PyFloat_AsDouble(item);
1134                                         Py_DECREF(item);
1135                                 }
1136
1137                                 switch(list_size)
1138                                 {
1139                                 case 2:
1140                                         {
1141                                                 float array2[2] = { array_data[0],array_data[1] };
1142 #ifdef SORT_UNIFORMS
1143                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array2, sizeof(float)*2);
1144 #else
1145                                                 SetUniform(loc, array2, 2);                                             
1146 #endif
1147                                                 Py_RETURN_NONE;
1148                                         } break;
1149                                 case 3:
1150                                         {
1151                                                 float array3[3] = { array_data[0],array_data[1],array_data[2] };
1152 #ifdef SORT_UNIFORMS
1153                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array3, sizeof(float)*3);
1154 #else
1155                                                 SetUniform(loc, array3, 3);     
1156 #endif
1157                                                 Py_RETURN_NONE;
1158                                         }break;
1159                                 case 4:
1160                                         {
1161                                                 float array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
1162 #ifdef SORT_UNIFORMS
1163                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array4, sizeof(float)*4);
1164 #else
1165                                                 SetUniform(loc, array4, 4);     
1166 #endif
1167                                                 Py_RETURN_NONE;
1168                                         }break;
1169                                 default:
1170                                         {
1171                                                 PyErr_Format(PyExc_TypeError, "Invalid list size");
1172                                                 return NULL;
1173                                         }break;
1174                                 }
1175                         }
1176                 }
1177         }
1178         return NULL;
1179 }
1180
1181 KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 or list4) )")
1182 {
1183         if(mError) {
1184                 Py_RETURN_NONE;
1185         }
1186         const char *uniform = "";
1187         PyObject *listPtr =0;
1188         int array_data[4] = {0,0,0,0};
1189
1190         if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
1191         {
1192                 int loc = GetUniformLocation(uniform);
1193                 if(loc != -1)
1194                 {
1195                         if(PySequence_Check(listPtr))
1196                         {
1197                                 unsigned int list_size = PySequence_Size(listPtr);
1198                                 
1199                                 for(unsigned int i=0; (i<list_size && i<4); i++)
1200                                 {
1201                                         PyObject *item = PySequence_GetItem(listPtr, i);
1202                                         array_data[i] = PyInt_AsLong(item);
1203                                         Py_DECREF(item);
1204                                 }
1205                                 switch(list_size)
1206                                 {
1207                                 case 2:
1208                                         {
1209                                                 int array2[2] = { array_data[0],array_data[1]};
1210 #ifdef SORT_UNIFORMS
1211                                                 SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
1212 #else
1213                                                 SetUniform(loc, array2, 2);                                             
1214 #endif
1215                                                 Py_RETURN_NONE;
1216                                         } break;
1217                                 case 3:
1218                                         {
1219                                                 int array3[3] = { array_data[0],array_data[1],array_data[2] };
1220 #ifdef SORT_UNIFORMS
1221                                                 SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
1222                                                 
1223 #else
1224                                                 SetUniform(loc, array3, 3);     
1225 #endif
1226                                                 Py_RETURN_NONE;
1227                                         }break;
1228                                 case 4:
1229                                         {
1230                                                 int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
1231 #ifdef SORT_UNIFORMS
1232                                                 SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
1233                                                 
1234 #else
1235                                                 SetUniform(loc, array4, 4);     
1236 #endif
1237                                                 Py_RETURN_NONE;
1238                                         }break;
1239                                 default:
1240                                         {
1241                                                 PyErr_Format(PyExc_TypeError, "Invalid list size");
1242                                                 return NULL;
1243                                         }break;
1244                                 }
1245                         }
1246                 }
1247         }
1248         return NULL;
1249 }
1250
1251
1252 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 
1253 "setUniformMatrix4(uniform-name, mat-4x4, transpose(row-major=true, col-major=false)" )
1254 {
1255         if(mError) {
1256                 Py_RETURN_NONE;
1257         }
1258
1259         float matr[16] = {
1260                 1,0,0,0,
1261                 0,1,0,0,
1262                 0,0,1,0,
1263                 0,0,0,1
1264         };
1265
1266         const char *uniform="";
1267         PyObject *matrix=0;
1268         int transp=1; // MT_ is row major so transpose by default....
1269         if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
1270         {
1271                 int loc = GetUniformLocation(uniform);
1272                 if(loc != -1)
1273                 {
1274                         if (PyObject_IsMT_Matrix(matrix, 4))
1275                         {
1276                                 MT_Matrix4x4 mat;
1277                                 if (PyMatTo(matrix, mat))
1278                                 {
1279 #ifdef SORT_UNIFORMS
1280                                         mat.getValue(matr);
1281                                         SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) );
1282 #else
1283                                         SetUniform(loc,mat,(transp!=0));
1284 #endif
1285                                         Py_RETURN_NONE;
1286                                 }
1287                         }
1288                 }
1289         }
1290         return NULL;
1291 }
1292
1293
1294 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
1295 "setUniformMatrix3(uniform-name, list[3x3], transpose(row-major=true, col-major=false)" )
1296 {
1297         if(mError) {
1298                 Py_RETURN_NONE;
1299         }
1300
1301         float matr[9] = {
1302                 1,0,0,
1303                 0,1,0,
1304                 0,0,1,
1305         };
1306
1307         const char *uniform="";
1308         PyObject *matrix=0;
1309         int transp=1; // MT_ is row major so transpose by default....
1310         if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
1311         {
1312                 int loc = GetUniformLocation(uniform);
1313                 if(loc != -1)
1314                 {
1315                         if (PyObject_IsMT_Matrix(matrix, 3))
1316                         {
1317                                 MT_Matrix3x3 mat;
1318                                 if (PyMatTo(matrix, mat))
1319                                 {
1320 #ifdef SORT_UNIFORMS
1321                                         mat.getValue(matr);
1322                                         SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) );
1323 #else
1324                                         SetUniform(loc,mat,(transp!=0));
1325 #endif
1326                                         Py_RETURN_NONE;
1327
1328                                 }
1329                         }
1330                 }
1331         }
1332         return NULL;
1333 }
1334
1335 KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
1336 {
1337         if(mError) {
1338                 Py_RETURN_NONE;
1339         }
1340         int attr=0;
1341         if(PyArg_ParseTuple(args, "i", &attr )) {
1342                 if(mShader==0) {
1343                         PyErr_Format(PyExc_ValueError, "invalid shader object");
1344                         return NULL;
1345                 }
1346                 mAttr=SHD_TANGENT;
1347                 glUseProgramObjectARB(mShader);
1348                 glBindAttribLocationARB(mShader, mAttr, "Tangent");
1349                 Py_RETURN_NONE;
1350         }
1351         return NULL;
1352 }
1353
1354
1355 KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
1356 {
1357         if(mError) {
1358                 Py_RETURN_NONE;
1359         }
1360
1361         const char *uniform="";
1362         int nloc=0;
1363         if(PyArg_ParseTuple(args, "si",&uniform, &nloc))
1364         {
1365                 int loc = GetUniformLocation(uniform);
1366                 if(loc != -1)
1367                 {
1368                         bool defined = false;
1369                         BL_UniformVecDef::iterator it = mPreDef.begin();
1370                         while(it != mPreDef.end()) {
1371                                 if((*it)->mLoc == loc) {
1372                                         defined = true;
1373                                         break;
1374                                 }
1375                                 it++;
1376                         }
1377                         if(defined)
1378                         {
1379                                 Py_RETURN_NONE;
1380                         }
1381
1382                         BL_DefUniform *uni = new BL_DefUniform();
1383                         uni->mLoc = loc;
1384                         uni->mType = nloc;
1385                         uni->mFlag = 0;
1386                         mPreDef.push_back(uni);
1387                         Py_RETURN_NONE;
1388                 }
1389         }
1390         return NULL;
1391 }
1392
1393 // eof