NLA SoC: Merge from 2.5
[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 (int)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 bool BL_Shader::Ok()const
112 {
113         return (mShader !=0 && mOk && mUse);
114 }
115
116 BL_Shader::BL_Shader()
117 :       PyObjectPlus(),
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 PyMethodDef BL_Shader::Methods[] = 
732 {
733         // creation
734         KX_PYMETHODTABLE( BL_Shader, setSource ),
735         KX_PYMETHODTABLE( BL_Shader, delSource ),
736         KX_PYMETHODTABLE( BL_Shader, getVertexProg ),
737         KX_PYMETHODTABLE( BL_Shader, getFragmentProg ),
738         KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ),
739         KX_PYMETHODTABLE( BL_Shader, validate),
740         /// access functions
741         KX_PYMETHODTABLE( BL_Shader, isValid),
742         KX_PYMETHODTABLE( BL_Shader, setUniform1f ),
743         KX_PYMETHODTABLE( BL_Shader, setUniform2f ),
744         KX_PYMETHODTABLE( BL_Shader, setUniform3f ),
745         KX_PYMETHODTABLE( BL_Shader, setUniform4f ),
746         KX_PYMETHODTABLE( BL_Shader, setUniform1i ),
747         KX_PYMETHODTABLE( BL_Shader, setUniform2i ),
748         KX_PYMETHODTABLE( BL_Shader, setUniform3i ),
749         KX_PYMETHODTABLE( BL_Shader, setUniform4i ),
750         KX_PYMETHODTABLE( BL_Shader, setAttrib ),
751
752         KX_PYMETHODTABLE( BL_Shader, setUniformfv ),
753         KX_PYMETHODTABLE( BL_Shader, setUniformiv ),
754         KX_PYMETHODTABLE( BL_Shader, setUniformDef ),
755
756         KX_PYMETHODTABLE( BL_Shader, setSampler  ),
757         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ),
758         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ),
759
760         {NULL,NULL} //Sentinel
761 };
762
763 PyAttributeDef BL_Shader::Attributes[] = {
764         { NULL }        //Sentinel
765 };
766
767 PyTypeObject BL_Shader::Type = {
768 #if (PY_VERSION_HEX >= 0x02060000)
769         PyVarObject_HEAD_INIT(NULL, 0)
770 #else
771         /* python 2.5 and below */
772         PyObject_HEAD_INIT( NULL )  /* required py macro */
773         0,                          /* ob_size */
774 #endif
775                 "BL_Shader",
776                 sizeof(PyObjectPlus_Proxy),
777                 0,
778                 py_base_dealloc,
779                 0,
780                 0,
781                 0,
782                 0,
783                 py_base_repr,
784                 0,0,0,0,0,0,0,0,0,
785                 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
786                 0,0,0,0,0,0,0,
787                 Methods,
788                 0,
789                 0,
790                 &PyObjectPlus::Type,
791                 0,0,0,0,0,0,
792                 py_base_new
793 };
794
795 KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" )
796 {
797         if(mShader !=0 && mOk  )
798         {
799                 // already set...
800                 Py_RETURN_NONE;
801         }
802         char *v,*f;
803         int apply=0;
804         if( PyArg_ParseTuple(args, "ssi:setSource", &v, &f, &apply) )
805         {
806                 vertProg = v;
807                 fragProg = f;
808                 if( LinkProgram() ) {
809                         glUseProgramObjectARB( mShader );
810                         mUse = apply!=0;
811                         Py_RETURN_NONE;
812                 }
813                 vertProg = 0;
814                 fragProg = 0;
815                 mUse = 0;
816                 Py_RETURN_NONE;
817         }
818         return NULL;
819 }
820
821
822 KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" )
823 {
824         ClearUniforms();
825         glUseProgramObjectARB(0);
826
827         glDeleteObjectARB(mShader);
828         mShader         = 0;
829         mOk                     = 0;
830         mUse            = 0;
831         Py_RETURN_NONE;
832 }
833
834 KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" )
835 {
836         return PyLong_FromSsize_t( ( mShader !=0 &&  mOk ) );
837 }
838
839 KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" )
840 {
841         return PyUnicode_FromString(vertProg?vertProg:"");
842 }
843
844 KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" )
845 {
846         return PyUnicode_FromString(fragProg?fragProg:"");
847 }
848
849 KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()")
850 {
851         if(mError) {
852                 Py_RETURN_NONE;
853         }
854         if(mShader==0) {
855                 PyErr_SetString(PyExc_TypeError, "shader.validate(): BL_Shader, invalid shader object");
856                 return NULL;
857         }
858         int stat = 0;
859         glValidateProgramARB(mShader);
860         glGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB,(GLint*) &stat);
861
862
863         if(stat > 0 && stat < MAX_LOG_LEN) {
864                 int char_len=0;
865                 char *logInf = (char*)MEM_mallocN(stat, "validate-log");
866
867                 glGetInfoLogARB(mShader, stat,(GLsizei*) &char_len, logInf);
868                 if(char_len >0) {
869                         spit("---- GLSL Validation ----");
870                         spit(logInf);
871                 }
872                 MEM_freeN(logInf);
873                 logInf=0;
874         }
875         Py_RETURN_NONE;
876 }
877
878
879 KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
880 {
881         if(mError) {
882                 Py_RETURN_NONE;
883         }
884
885         const char *uniform="";
886         int index=-1;
887         if(PyArg_ParseTuple(args, "si:setSampler", &uniform, &index)) 
888         {
889                 int loc = GetUniformLocation(uniform);
890                 if(loc != -1) {
891                         if(index >= MAXTEX &&  index < 0)
892                                 spit("Invalid texture sample index: " << index);
893
894 #ifdef SORT_UNIFORMS
895                         SetUniformiv(loc, BL_Uniform::UNI_INT, &index, (sizeof(int)) );
896 #else
897                         SetUniform(loc, index);
898 #endif
899                         //if(index <= MAXTEX)
900                         //      mSampler[index].mLoc = loc;
901                         //else
902                         //      spit("Invalid texture sample index: " << index);
903                 }
904                 Py_RETURN_NONE;
905         }
906         return NULL;
907 }
908
909 KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" )
910 {
911         int pass = 1;
912         if(!PyArg_ParseTuple(args, "i:setNumberOfPasses", &pass))
913                 return NULL;
914
915         mPass = 1;
916         Py_RETURN_NONE;
917 }
918
919 /// access functions
920 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
921 {
922         if(mError) {
923                 Py_RETURN_NONE;
924         }
925
926         const char *uniform="";
927         float value=0;
928         if(PyArg_ParseTuple(args, "sf:setUniform1f", &uniform, &value ))
929         {
930                 int loc = GetUniformLocation(uniform);
931                 if(loc != -1)
932                 {
933 #ifdef SORT_UNIFORMS
934                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT, &value, sizeof(float));
935 #else                   
936                         SetUniform( loc, (float)value );
937 #endif
938                 }
939                 Py_RETURN_NONE;
940         }
941         return NULL;
942 }
943
944
945 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
946 {
947         if(mError) {
948                 Py_RETURN_NONE;
949         }
950         const char *uniform="";
951         float array[2]={ 0,0 };
952         if(PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] ))
953         {
954                 int loc = GetUniformLocation(uniform);
955                 if(loc != -1)
956                 {
957 #ifdef SORT_UNIFORMS
958                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array, (sizeof(float)*2) );
959 #else
960                         SetUniform(loc, array, 2);
961 #endif
962                 }
963                 Py_RETURN_NONE;
964         }
965         return NULL;
966 }
967
968
969 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
970 {
971         if(mError) {
972                 Py_RETURN_NONE;
973         }
974         const char *uniform="";
975         float array[3]={0,0,0};
976         if(PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2]))
977         {
978                 int loc = GetUniformLocation(uniform);
979                 if(loc != -1)
980                 {
981 #ifdef SORT_UNIFORMS
982                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array, (sizeof(float)*3) );
983 #else
984                         SetUniform(loc, array, 3);
985 #endif
986                 }
987                 Py_RETURN_NONE;
988
989         }
990         return NULL;
991 }
992
993
994 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
995 {
996         if(mError) {
997                 Py_RETURN_NONE;
998         }
999         const char *uniform="";
1000         float array[4]={0,0,0,0};
1001         if(PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3]))
1002         {
1003                 int loc = GetUniformLocation(uniform);
1004                 if(loc != -1)
1005                 {
1006 #ifdef SORT_UNIFORMS
1007                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array, (sizeof(float)*4) );
1008 #else
1009                         SetUniform(loc, array, 4);
1010 #endif
1011                 }
1012                 Py_RETURN_NONE;
1013         }
1014         return NULL;
1015 }
1016
1017
1018 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
1019 {
1020         if(mError) {
1021                 Py_RETURN_NONE;
1022         }
1023         const char *uniform="";
1024         int value=0;
1025         if(PyArg_ParseTuple(args, "si:setUniform1i", &uniform, &value ))
1026         {
1027                 int loc = GetUniformLocation(uniform);
1028                 if(loc != -1)
1029                 {
1030 #ifdef SORT_UNIFORMS
1031                         SetUniformiv(loc, BL_Uniform::UNI_INT, &value, sizeof(int));
1032 #else
1033                         SetUniform(loc, (int)value);
1034 #endif
1035                 }
1036                 Py_RETURN_NONE;
1037         }
1038         return NULL;
1039 }
1040
1041
1042 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
1043 {
1044         if(mError) {
1045                 Py_RETURN_NONE;
1046         }
1047         const char *uniform="";
1048         int array[2]={ 0,0 };
1049         if(PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] ))
1050         {
1051                 int loc = GetUniformLocation(uniform);
1052                 if(loc != -1)
1053                 {
1054 #ifdef SORT_UNIFORMS
1055                         SetUniformiv(loc, BL_Uniform::UNI_INT2, array, sizeof(int)*2);
1056 #else
1057                         SetUniform(loc, array, 2);
1058 #endif
1059                 }
1060                 Py_RETURN_NONE;
1061         }
1062         return NULL;
1063 }
1064
1065
1066 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
1067 {
1068         if(mError) {
1069                 Py_RETURN_NONE;
1070         }
1071
1072         const char *uniform="";
1073         int array[3]={0,0,0};
1074         if(PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2]))
1075         {
1076                 int loc = GetUniformLocation(uniform);
1077                 if(loc != -1)
1078                 {
1079 #ifdef SORT_UNIFORMS
1080                         SetUniformiv(loc, BL_Uniform::UNI_INT3, array, sizeof(int)*3);
1081 #else
1082                         SetUniform(loc, array, 3);
1083 #endif
1084                 }
1085                 Py_RETURN_NONE;
1086         }
1087         return NULL;
1088 }
1089
1090 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
1091 {
1092         if(mError) {
1093                 Py_RETURN_NONE;
1094         }
1095         const char *uniform="";
1096         int array[4]={0,0,0, 0};
1097         if(PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] ))
1098         {
1099                 int loc = GetUniformLocation(uniform);
1100                 if(loc != -1)
1101                 {
1102 #ifdef SORT_UNIFORMS
1103                         SetUniformiv(loc, BL_Uniform::UNI_INT4, array, sizeof(int)*4);
1104 #else
1105                         SetUniform(loc, array, 4);
1106 #endif
1107                 }
1108                 Py_RETURN_NONE;
1109         }
1110         return NULL;
1111 }
1112
1113 KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )")
1114 {
1115         if(mError) {
1116                 Py_RETURN_NONE;
1117         }
1118         const char *uniform = "";
1119         PyObject *listPtr =0;
1120         float array_data[4] = {0.f,0.f,0.f,0.f};
1121
1122         if(PyArg_ParseTuple(args, "sO:setUniformfv", &uniform, &listPtr))
1123         {
1124                 int loc = GetUniformLocation(uniform);
1125                 if(loc != -1)
1126                 {
1127                         if(PySequence_Check(listPtr))
1128                         {
1129                                 unsigned int list_size = PySequence_Size(listPtr);
1130                                 
1131                                 for(unsigned int i=0; (i<list_size && i<4); i++)
1132                                 {
1133                                         PyObject *item = PySequence_GetItem(listPtr, i);
1134                                         array_data[i] = (float)PyFloat_AsDouble(item);
1135                                         Py_DECREF(item);
1136                                 }
1137
1138                                 switch(list_size)
1139                                 {
1140                                 case 2:
1141                                         {
1142                                                 float array2[2] = { array_data[0],array_data[1] };
1143 #ifdef SORT_UNIFORMS
1144                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array2, sizeof(float)*2);
1145 #else
1146                                                 SetUniform(loc, array2, 2);                                             
1147 #endif
1148                                                 Py_RETURN_NONE;
1149                                         } break;
1150                                 case 3:
1151                                         {
1152                                                 float array3[3] = { array_data[0],array_data[1],array_data[2] };
1153 #ifdef SORT_UNIFORMS
1154                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array3, sizeof(float)*3);
1155 #else
1156                                                 SetUniform(loc, array3, 3);     
1157 #endif
1158                                                 Py_RETURN_NONE;
1159                                         }break;
1160                                 case 4:
1161                                         {
1162                                                 float array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
1163 #ifdef SORT_UNIFORMS
1164                                                 SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array4, sizeof(float)*4);
1165 #else
1166                                                 SetUniform(loc, array4, 4);     
1167 #endif
1168                                                 Py_RETURN_NONE;
1169                                         }break;
1170                                 default:
1171                                         {
1172                                                 PyErr_SetString(PyExc_TypeError, "shader.setUniform4i(name, ix,iy,iz, iw): BL_Shader. invalid list size");
1173                                                 return NULL;
1174                                         }break;
1175                                 }
1176                         }
1177                 }
1178         }
1179         return NULL;
1180 }
1181
1182 KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 or list3 or list4) )")
1183 {
1184         if(mError) {
1185                 Py_RETURN_NONE;
1186         }
1187         const char *uniform = "";
1188         PyObject *listPtr =0;
1189         int array_data[4] = {0,0,0,0};
1190
1191         if(!PyArg_ParseTuple(args, "sO:setUniformiv", &uniform, &listPtr))
1192                 return NULL;
1193         
1194         int loc = GetUniformLocation(uniform);
1195         
1196         if(loc == -1) {
1197                 PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, first string argument is not a valid uniform value");
1198                 return NULL;
1199         }
1200         
1201         if(!PySequence_Check(listPtr)) {
1202                 PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument is not a sequence");
1203                 return NULL;
1204         }
1205         
1206         unsigned int list_size = PySequence_Size(listPtr);
1207         
1208         for(unsigned int i=0; (i<list_size && i<4); i++)
1209         {
1210                 PyObject *item = PySequence_GetItem(listPtr, i);
1211                 array_data[i] = PyLong_AsSsize_t(item);
1212                 Py_DECREF(item);
1213         }
1214         
1215         if(PyErr_Occurred()) {
1216                 PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, one or more values in the list is not an int");
1217                 return NULL;
1218         }
1219         
1220         /* Sanity checks done! */
1221         
1222         switch(list_size)
1223         {
1224         case 2:
1225                 {
1226                         int array2[2] = { array_data[0],array_data[1]};
1227 #ifdef SORT_UNIFORMS
1228                         SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
1229 #else
1230                         SetUniform(loc, array2, 2);                                             
1231 #endif
1232                         Py_RETURN_NONE;
1233                 } break;
1234         case 3:
1235                 {
1236                         int array3[3] = { array_data[0],array_data[1],array_data[2] };
1237 #ifdef SORT_UNIFORMS
1238                         SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
1239                         
1240 #else
1241                         SetUniform(loc, array3, 3);     
1242 #endif
1243                         Py_RETURN_NONE;
1244                 }break;
1245         case 4:
1246                 {
1247                         int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
1248 #ifdef SORT_UNIFORMS
1249                         SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
1250                         
1251 #else
1252                         SetUniform(loc, array4, 4);     
1253 #endif
1254                         Py_RETURN_NONE;
1255                 }break;
1256         default:
1257                 {
1258                         PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument, invalid list size, expected an int list between 2 and 4");
1259                         return NULL;
1260                 }break;
1261         }
1262         
1263         Py_RETURN_NONE;
1264 }
1265
1266
1267 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 
1268 "setUniformMatrix4(uniform_name, mat-4x4, transpose(row-major=true, col-major=false)" )
1269 {
1270         if(mError) {
1271                 Py_RETURN_NONE;
1272         }
1273
1274         float matr[16] = {
1275                 1,0,0,0,
1276                 0,1,0,0,
1277                 0,0,1,0,
1278                 0,0,0,1
1279         };
1280
1281         const char *uniform="";
1282         PyObject *matrix=0;
1283         int transp=1; // MT_ is row major so transpose by default....
1284         
1285         if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix4",&uniform, &matrix,&transp))
1286                 return NULL;
1287
1288         int loc = GetUniformLocation(uniform);
1289         
1290         if(loc == -1) {
1291                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, first string argument is not a valid uniform value");
1292                 return NULL;
1293         }
1294         
1295         MT_Matrix4x4 mat;
1296         
1297         if (!PyMatTo(matrix, mat)) {
1298                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, second argument cannot be converted into a 4x4 matrix");
1299                 return NULL;
1300         }
1301         
1302         /* Sanity checks done! */
1303
1304 #ifdef SORT_UNIFORMS
1305         mat.getValue(matr);
1306         SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) );
1307 #else
1308         SetUniform(loc,mat,(transp!=0));
1309 #endif
1310         Py_RETURN_NONE;
1311 }
1312
1313
1314 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
1315 "setUniformMatrix3(uniform_name, list[3x3], transpose(row-major=true, col-major=false)" )
1316 {
1317         if(mError) {
1318                 Py_RETURN_NONE;
1319         }
1320
1321         float matr[9] = {
1322                 1,0,0,
1323                 0,1,0,
1324                 0,0,1,
1325         };
1326
1327         const char *uniform="";
1328         PyObject *matrix=0;
1329         int transp=1; // MT_ is row major so transpose by default....
1330         if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix3",&uniform, &matrix,&transp))
1331                 return NULL;
1332         
1333         int loc = GetUniformLocation(uniform);
1334         
1335         if(loc == -1) {
1336                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, first string argument is not a valid uniform value");
1337                 return NULL;
1338         }
1339         
1340         
1341         MT_Matrix3x3 mat;
1342         
1343         if (!PyMatTo(matrix, mat)) {
1344                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, second argument cannot be converted into a 3x3 matrix");
1345                 return NULL;
1346         }
1347         
1348
1349 #ifdef SORT_UNIFORMS
1350         mat.getValue(matr);
1351         SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) );
1352 #else
1353         SetUniform(loc,mat,(transp!=0));
1354 #endif
1355         Py_RETURN_NONE;
1356 }
1357
1358 KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
1359 {
1360         if(mError) {
1361                 Py_RETURN_NONE;
1362         }
1363         
1364         int attr=0;
1365         
1366         if(!PyArg_ParseTuple(args, "i:setAttrib", &attr ))
1367                 return NULL;
1368         
1369         if(mShader==0) {
1370                 PyErr_SetString(PyExc_ValueError, "shader.setAttrib() BL_Shader, invalid shader object");
1371                 return NULL;
1372         }
1373         mAttr=SHD_TANGENT; /* What the heck is going on here - attr is just ignored??? - Campbell */
1374         glUseProgramObjectARB(mShader);
1375         glBindAttribLocationARB(mShader, mAttr, "Tangent");
1376         Py_RETURN_NONE;
1377 }
1378
1379
1380 KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
1381 {
1382         if(mError) {
1383                 Py_RETURN_NONE;
1384         }
1385
1386         const char *uniform="";
1387         int nloc=0;
1388         if(PyArg_ParseTuple(args, "si:setUniformDef",&uniform, &nloc))
1389         {
1390                 int loc = GetUniformLocation(uniform);
1391                 if(loc != -1)
1392                 {
1393                         bool defined = false;
1394                         BL_UniformVecDef::iterator it = mPreDef.begin();
1395                         while(it != mPreDef.end()) {
1396                                 if((*it)->mLoc == loc) {
1397                                         defined = true;
1398                                         break;
1399                                 }
1400                                 it++;
1401                         }
1402                         if(defined)
1403                         {
1404                                 Py_RETURN_NONE;
1405                         }
1406
1407                         BL_DefUniform *uni = new BL_DefUniform();
1408                         uni->mLoc = loc;
1409                         uni->mType = nloc;
1410                         uni->mFlag = 0;
1411                         mPreDef.push_back(uni);
1412                         Py_RETURN_NONE;
1413                 }
1414         }
1415         return NULL;
1416 }
1417
1418 // eof