add missing files after merging
[blender.git] / source / gameengine / Ketsji / BL_Shader.cpp
1 /** \file gameengine/Ketsji/BL_Shader.cpp
2  *  \ingroup ketsji
3  */
4
5 #include "GL/glew.h"
6
7 #include <iostream>
8 #include "BL_Shader.h"
9 #include "BL_Material.h"
10
11 #include "MT_assert.h"
12 #include "MT_Matrix4x4.h"
13 #include "MT_Matrix3x3.h"
14 #include "KX_PyMath.h"
15 #include "MEM_guardedalloc.h"
16
17 #include "RAS_GLExtensionManager.h"
18 #include "RAS_MeshObject.h"
19 #include "RAS_IRasterizer.h"
20
21 #define spit(x) std::cout << x << std::endl;
22
23 #define SORT_UNIFORMS 1
24 #define UNIFORM_MAX_LEN (int)sizeof(float)*16
25 #define MAX_LOG_LEN 262144 // bounds
26
27 BL_Uniform::BL_Uniform(int data_size)
28 :       mLoc(-1),
29         mDirty(true),
30         mType(UNI_NONE),
31         mTranspose(0),
32         mDataLen(data_size)
33 {
34 #ifdef SORT_UNIFORMS
35         MT_assert((int)mDataLen <= UNIFORM_MAX_LEN);
36         mData = (void*)MEM_mallocN(mDataLen, "shader-uniform-alloc");
37 #endif
38 }
39
40 BL_Uniform::~BL_Uniform()
41 {
42 #ifdef SORT_UNIFORMS
43         if(mData) {
44                 MEM_freeN(mData);
45                 mData=0;
46         }
47 #endif
48 }
49
50 void BL_Uniform::Apply(class BL_Shader *shader)
51 {
52 #ifdef SORT_UNIFORMS
53         MT_assert(mType > UNI_NONE && mType < UNI_MAX && mData);
54
55         if(!mDirty) 
56                 return;
57
58         switch(mType)
59         {
60         case UNI_FLOAT: {
61                         float *f = (float*)mData;
62                         glUniform1fARB(mLoc,(GLfloat)*f);
63                 }break;
64         case UNI_INT: {
65                         int *f = (int*)mData;
66                         glUniform1iARB(mLoc, (GLint)*f);
67                 }break;
68         case UNI_FLOAT2: {
69                         float *f = (float*)mData;
70                         glUniform2fvARB(mLoc,1, (GLfloat*)f);
71                 }break;
72         case UNI_FLOAT3: {
73                         float *f = (float*)mData;
74                         glUniform3fvARB(mLoc,1,(GLfloat*)f);
75                 }break;
76         case UNI_FLOAT4: {
77                         float *f = (float*)mData;
78                         glUniform4fvARB(mLoc,1,(GLfloat*)f);
79                 }break;
80         case UNI_INT2: {
81                         int *f = (int*)mData;
82                         glUniform2ivARB(mLoc,1,(GLint*)f);
83                 }break; 
84         case UNI_INT3: {
85                         int *f = (int*)mData;
86                         glUniform3ivARB(mLoc,1,(GLint*)f);
87                 }break; 
88         case UNI_INT4: {
89                         int *f = (int*)mData;
90                         glUniform4ivARB(mLoc,1,(GLint*)f);
91                 }break;
92         case UNI_MAT4: {
93                         float *f = (float*)mData;
94                         glUniformMatrix4fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f);
95                 }break;
96         case UNI_MAT3: {
97                         float *f = (float*)mData;
98                         glUniformMatrix3fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f);
99                 }break;
100         }
101         mDirty = false;
102 #endif
103 }
104
105 void BL_Uniform::SetData(int location, int type,bool transpose)
106 {
107 #ifdef SORT_UNIFORMS
108         mType   = type;
109         mLoc    = location;
110         mDirty  = true;
111 #endif
112 }
113
114 bool BL_Shader::Ok()const
115 {
116         return (mShader !=0 && mOk && mUse);
117 }
118
119 BL_Shader::BL_Shader()
120 :       PyObjectPlus(),
121         mShader(0),
122         mPass(1),
123         mOk(0),
124         mUse(0),
125         mAttr(0),
126         vertProg(""),
127         fragProg(""),
128         mError(0),
129         mDirty(true)
130 {
131         // if !GLEW_ARB_shader_objects this class will not be used
132         //for (int i=0; i<MAXTEX; i++) {
133         //      mSampler[i] = BL_Sampler();
134         //}
135 }
136
137 BL_Shader::~BL_Shader()
138 {
139         //for (int i=0; i<MAXTEX; i++){
140         //      if(mSampler[i].mOwn) {
141         //              if(mSampler[i].mTexture)
142         //                      mSampler[i].mTexture->DeleteTex();
143         //      }
144         //}
145         ClearUniforms();
146
147         if( mShader ) {
148                 glDeleteObjectARB(mShader);
149                 mShader = 0;
150         }
151         vertProg        = 0;
152         fragProg        = 0;
153         mOk                     = 0;
154         glUseProgramObjectARB(0);
155 }
156
157 void BL_Shader::ClearUniforms()
158 {
159         BL_UniformVec::iterator it = mUniforms.begin();
160         while(it != mUniforms.end()){
161                 delete (*it);
162                 it++;
163         }
164         mUniforms.clear();
165
166         
167         BL_UniformVecDef::iterator itp = mPreDef.begin();
168         while(itp != mPreDef.end()) {
169                 delete (*itp);
170                 itp++;
171         }
172         mPreDef.clear();
173
174 }
175
176
177 BL_Uniform  *BL_Shader::FindUniform(const int location)
178 {
179 #ifdef SORT_UNIFORMS
180         BL_UniformVec::iterator it = mUniforms.begin();
181         while(it != mUniforms.end()) {
182                 if((*it)->GetLocation() == location)
183                         return (*it);
184                 it++;
185         }
186 #endif
187         return 0;
188 }
189
190 void BL_Shader::SetUniformfv(int location, int type, float *param,int size, bool transpose)
191 {
192 #ifdef SORT_UNIFORMS
193         BL_Uniform *uni= FindUniform(location);
194         if(uni) {
195                 memcpy(uni->getData(), param, size);
196                 uni->SetData(location, type, transpose);
197         }
198         else {
199                 uni = new BL_Uniform(size);
200                 memcpy(uni->getData(), param, size);
201
202                 uni->SetData(location, type, transpose);
203                 mUniforms.push_back(uni);
204         }
205         mDirty = true;
206 #endif
207 }
208
209 void BL_Shader::SetUniformiv(int location, int type, int *param,int size, bool transpose)
210 {
211 #ifdef SORT_UNIFORMS
212         BL_Uniform *uni= FindUniform(location);
213         if(uni) {
214                 memcpy(uni->getData(), param, size);
215                 uni->SetData(location, type, transpose);
216         }
217         else {
218                 uni = new BL_Uniform(size);
219                 memcpy(uni->getData(), param, size);
220                 uni->SetData(location, type, transpose);
221                 mUniforms.push_back(uni);
222         }
223         mDirty = true;
224 #endif
225 }
226
227
228 void BL_Shader::ApplyShader()
229 {
230 #ifdef SORT_UNIFORMS
231         if(!mDirty) 
232                 return;
233
234         for(unsigned int i=0; i<mUniforms.size(); i++)
235                 mUniforms[i]->Apply(this);
236
237         mDirty = false;
238 #endif
239 }
240
241 void BL_Shader::UnloadShader()
242 {
243         //
244 }
245
246
247 bool BL_Shader::LinkProgram()
248 {
249         int vertlen = 0, fraglen=0, proglen=0;
250         int vertstatus=0, fragstatus=0, progstatus=0;
251         unsigned int tmpVert=0, tmpFrag=0, tmpProg=0;
252         int char_len=0;
253         char *logInf =0;
254
255         if(mError)
256                 goto programError;
257
258         if(!vertProg || !fragProg){
259                 spit("Invalid GLSL sources");
260                 return false;
261         }
262         if( !GLEW_ARB_fragment_shader) {
263                 spit("Fragment shaders not supported");
264                 return false;
265         }
266         if( !GLEW_ARB_vertex_shader) {
267                 spit("Vertex shaders not supported");
268                 return false;
269         }
270         
271         // -- vertex shader ------------------
272         tmpVert = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
273         glShaderSourceARB(tmpVert, 1, (const char**)&vertProg, 0);
274         glCompileShaderARB(tmpVert);
275         glGetObjectParameterivARB(tmpVert, GL_OBJECT_INFO_LOG_LENGTH_ARB,(GLint*) &vertlen);
276         
277         // print info if any
278         if( vertlen > 0 && vertlen < MAX_LOG_LEN){
279                 logInf = (char*)MEM_mallocN(vertlen, "vert-log");
280                 glGetInfoLogARB(tmpVert, vertlen, (GLsizei*)&char_len, logInf);
281                 if(char_len >0) {
282                         spit("---- Vertex Shader Error ----");
283                         spit(logInf);
284                 }
285                 MEM_freeN(logInf);
286                 logInf=0;
287         }
288         // check for compile errors
289         glGetObjectParameterivARB(tmpVert, GL_OBJECT_COMPILE_STATUS_ARB,(GLint*)&vertstatus);
290         if(!vertstatus) {
291                 spit("---- Vertex shader failed to compile ----");
292                 goto programError;
293         }
294
295         // -- fragment shader ----------------
296         tmpFrag = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
297         glShaderSourceARB(tmpFrag, 1,(const char**)&fragProg, 0);
298         glCompileShaderARB(tmpFrag);
299         glGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &fraglen);
300         if(fraglen >0 && fraglen < MAX_LOG_LEN){
301                 logInf = (char*)MEM_mallocN(fraglen, "frag-log");
302                 glGetInfoLogARB(tmpFrag, fraglen,(GLsizei*) &char_len, logInf);
303                 if(char_len >0) {
304                         spit("---- Fragment Shader Error ----");
305                         spit(logInf);
306                 }
307                 MEM_freeN(logInf);
308                 logInf=0;
309         }
310
311         glGetObjectParameterivARB(tmpFrag, GL_OBJECT_COMPILE_STATUS_ARB, (GLint*) &fragstatus);
312         if(!fragstatus){
313                 spit("---- Fragment shader failed to compile ----");
314                 goto programError;
315         }
316
317         
318         // -- program ------------------------
319         //  set compiled vert/frag shader & link
320         tmpProg = glCreateProgramObjectARB();
321         glAttachObjectARB(tmpProg, tmpVert);
322         glAttachObjectARB(tmpProg, tmpFrag);
323         glLinkProgramARB(tmpProg);
324         glGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &proglen);
325         glGetObjectParameterivARB(tmpProg, GL_OBJECT_LINK_STATUS_ARB, (GLint*) &progstatus);
326         
327
328         if(proglen > 0 && proglen < MAX_LOG_LEN) {
329                 logInf = (char*)MEM_mallocN(proglen, "prog-log");
330                 glGetInfoLogARB(tmpProg, proglen, (GLsizei*)&char_len, logInf);
331                 if(char_len >0) {
332                         spit("---- GLSL Program ----");
333                         spit(logInf);
334                 }
335                 MEM_freeN(logInf);
336                 logInf=0;
337         }
338
339         if(!progstatus){
340                 spit("---- GLSL program failed to link ----");
341                 goto programError;
342         }
343
344         // set
345         mShader = tmpProg;
346         glDeleteObjectARB(tmpVert);
347         glDeleteObjectARB(tmpFrag);
348         mOk             = 1;
349         mError = 0;
350         return true;
351
352 programError:
353         if(tmpVert) {
354                 glDeleteObjectARB(tmpVert);
355                 tmpVert=0;
356         }
357         if(tmpFrag) {
358                 glDeleteObjectARB(tmpFrag);
359                 tmpFrag=0;
360         }
361
362         if(tmpProg) {
363                 glDeleteObjectARB(tmpProg);
364                 tmpProg=0;
365         }
366
367         mOk             = 0;
368         mUse    = 0;
369         mError  = 1;
370         return false;
371 }
372
373 const char *BL_Shader::GetVertPtr()
374 {
375         return vertProg?vertProg:0;
376 }
377
378 const char *BL_Shader::GetFragPtr()
379 {
380         return fragProg?fragProg:0;
381 }
382
383 void BL_Shader::SetVertPtr( char *vert )
384 {
385         vertProg = vert;
386 }
387
388 void BL_Shader::SetFragPtr( char *frag )
389 {
390         fragProg = frag;
391 }
392
393 unsigned int BL_Shader::GetProg()
394
395         return mShader;
396 }
397 //
398 //const BL_Sampler* BL_Shader::GetSampler(int i)
399 //{
400 //      MT_assert(i<=MAXTEX);
401 //      return &mSampler[i];
402 //}
403
404 void BL_Shader::SetSampler(int loc, int unit)
405 {
406         if( GLEW_ARB_fragment_shader &&
407                 GLEW_ARB_vertex_shader &&
408                 GLEW_ARB_shader_objects 
409                 )
410         {
411                 glUniform1iARB(loc, unit);
412         }
413 }
414 //
415 //void BL_Shader::InitializeSampler(int unit, BL_Texture* texture)
416 //{
417 //      MT_assert(unit<=MAXTEX);
418 //      mSampler[unit].mTexture = texture;
419 //      mSampler[unit].mLoc =-1;
420 //      mSampler[unit].mOwn = 0;
421 //}
422
423 void BL_Shader::SetProg(bool enable)
424 {
425         if( GLEW_ARB_fragment_shader &&
426                 GLEW_ARB_vertex_shader &&
427                 GLEW_ARB_shader_objects 
428                 )
429         {
430                 if(     mShader != 0 && mOk && enable) {
431                         glUseProgramObjectARB(mShader);
432                 }
433                 else {
434                         glUseProgramObjectARB(0);       
435                 }
436         }
437 }
438
439 void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
440 {
441         if(!Ok() || !mPreDef.size()) 
442                 return;
443
444         if( GLEW_ARB_fragment_shader &&
445                 GLEW_ARB_vertex_shader &&
446                 GLEW_ARB_shader_objects 
447                 )
448         {
449                 MT_Matrix4x4 model;
450                 model.setValue(ms.m_OpenGLMatrix);
451                 const MT_Matrix4x4& view = rasty->GetViewMatrix();
452
453                 if(mAttr==SHD_TANGENT)
454                          ms.m_mesh->SetMeshModified(true);
455
456                 BL_UniformVecDef::iterator it;
457                 for(it = mPreDef.begin(); it!= mPreDef.end(); it++)
458                 {
459                         BL_DefUniform *uni = (*it);
460                         if(uni->mLoc == -1) continue;
461
462                         switch (uni->mType)
463                         {
464                                 case MODELMATRIX:
465                                         {
466                                                 SetUniform(uni->mLoc, model);
467                                                 break;
468                                         }
469                                 case MODELMATRIX_TRANSPOSE:
470                                         {
471                                                 SetUniform(uni->mLoc, model, true);
472                                                 break;
473                                         }
474                                 case MODELMATRIX_INVERSE:
475                                         {
476                                                 model.invert();
477                                                 SetUniform(uni->mLoc, model);
478                                                 break;
479                                         }
480                                 case MODELMATRIX_INVERSETRANSPOSE:
481                                         {
482                                                 model.invert();
483                                                 SetUniform(uni->mLoc, model, true);
484                                                 break;
485                                         }
486                                 case MODELVIEWMATRIX:
487                                         {
488                                                 SetUniform(uni->mLoc, view*model);
489                                                 break;
490                                         }
491
492                                 case MODELVIEWMATRIX_TRANSPOSE:
493                                         {
494                                                 MT_Matrix4x4 mat(view*model);
495                                                 SetUniform(uni->mLoc, mat, true);
496                                                 break;
497                                         }
498                                 case MODELVIEWMATRIX_INVERSE:
499                                         {
500                                                 MT_Matrix4x4 mat(view*model);
501                                                 mat.invert();
502                                                 SetUniform(uni->mLoc, mat);
503                                                 break;
504                                         }
505                                 case MODELVIEWMATRIX_INVERSETRANSPOSE:
506                                         {
507                                                 MT_Matrix4x4 mat(view*model);
508                                                 mat.invert();
509                                                 SetUniform(uni->mLoc, mat, true);
510                                                 break;
511                                         }
512                                 case CAM_POS:
513                                         {
514                                                 MT_Point3 pos(rasty->GetCameraPosition());
515                                                 SetUniform(uni->mLoc, pos);
516                                                 break;
517                                         }
518                                 case VIEWMATRIX:
519                                         {
520                                                 SetUniform(uni->mLoc, view);
521                                                 break;
522                                         }
523                                 case VIEWMATRIX_TRANSPOSE:
524                                         {
525                                                 SetUniform(uni->mLoc, view, true);
526                                                 break;
527                                         }
528                                 case VIEWMATRIX_INVERSE:
529                                         {
530                                                 MT_Matrix4x4 viewinv = view;
531                                                 viewinv.invert();
532                                                 SetUniform(uni->mLoc, view);
533                                                 break;
534                                         }
535                                 case VIEWMATRIX_INVERSETRANSPOSE:
536                                         {
537                                                 MT_Matrix4x4 viewinv = view;
538                                                 viewinv.invert();
539                                                 SetUniform(uni->mLoc, view, true);
540                                                 break;
541                                         }
542                                 case CONSTANT_TIMER:
543                                         {
544                                                 SetUniform(uni->mLoc, (float)rasty->GetTime());
545                                                 break;
546                                         }
547                                 default:
548                                         break;
549                         }
550                 }
551         }
552 }
553
554
555 int BL_Shader::GetAttribLocation(const STR_String& name)
556 {
557         if( GLEW_ARB_fragment_shader &&
558                 GLEW_ARB_vertex_shader &&
559                 GLEW_ARB_shader_objects 
560                 )
561         {
562                 return glGetAttribLocationARB(mShader, name.ReadPtr());
563         }
564
565         return -1;
566 }
567
568 void BL_Shader::BindAttribute(const STR_String& attr, int loc)
569 {
570         if( GLEW_ARB_fragment_shader &&
571                 GLEW_ARB_vertex_shader &&
572                 GLEW_ARB_shader_objects 
573                 )
574         {
575                 glBindAttribLocationARB(mShader, loc, attr.ReadPtr());
576         }
577 }
578
579 int BL_Shader::GetUniformLocation(const STR_String& name)
580 {
581         if( GLEW_ARB_fragment_shader &&
582                 GLEW_ARB_vertex_shader &&
583                 GLEW_ARB_shader_objects 
584                 )
585         {
586                 MT_assert(mShader!=0);
587                 int location = glGetUniformLocationARB(mShader, name.ReadPtr());
588                 if(location == -1)
589                         spit("Invalid uniform value: " << name.ReadPtr() << ".");
590                 return location;
591         }
592
593         return -1;
594 }
595
596 void BL_Shader::SetUniform(int uniform, const MT_Tuple2& vec)
597 {
598         if( GLEW_ARB_fragment_shader &&
599                 GLEW_ARB_vertex_shader &&
600                 GLEW_ARB_shader_objects 
601                 )
602         {
603                 float value[2];
604                 vec.getValue(value);
605                 glUniform2fvARB(uniform, 1, value);
606         }
607
608 }
609
610 void BL_Shader::SetUniform(int uniform, const MT_Tuple3& vec)
611 {
612         if( GLEW_ARB_fragment_shader &&
613                 GLEW_ARB_vertex_shader &&
614                 GLEW_ARB_shader_objects 
615                 )
616         {       
617                 float value[3];
618                 vec.getValue(value);
619                 glUniform3fvARB(uniform, 1, value);
620         }
621 }
622
623 void BL_Shader::SetUniform(int uniform, const MT_Tuple4& vec)
624 {
625         if( GLEW_ARB_fragment_shader &&
626                 GLEW_ARB_vertex_shader &&
627                 GLEW_ARB_shader_objects 
628                 )
629         {
630                 float value[4];
631                 vec.getValue(value);
632                 glUniform4fvARB(uniform, 1, value);
633         }
634 }
635
636 void BL_Shader::SetUniform(int uniform, const unsigned int& val)
637 {
638         if( GLEW_ARB_fragment_shader &&
639                 GLEW_ARB_vertex_shader &&
640                 GLEW_ARB_shader_objects 
641                 )
642         {
643                 glUniform1iARB(uniform, val);
644         }
645 }
646
647 void BL_Shader::SetUniform(int uniform, const int val)
648 {
649         if( GLEW_ARB_fragment_shader &&
650                 GLEW_ARB_vertex_shader &&
651                 GLEW_ARB_shader_objects 
652                 )
653         {
654                 glUniform1iARB(uniform, val);
655         }
656 }
657
658 void BL_Shader::SetUniform(int uniform, const float& val)
659 {
660         if( GLEW_ARB_fragment_shader &&
661                 GLEW_ARB_vertex_shader &&
662                 GLEW_ARB_shader_objects 
663                 )
664         {
665                 glUniform1fARB(uniform, val);
666         }
667 }
668
669 void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose)
670 {
671         if( GLEW_ARB_fragment_shader &&
672                 GLEW_ARB_vertex_shader &&
673                 GLEW_ARB_shader_objects 
674                 )
675         {
676                 float value[16];
677                 // note: getValue gives back column major as needed by OpenGL
678                 vec.getValue(value);
679                 glUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
680         }
681 }
682
683 void BL_Shader::SetUniform(int uniform, const MT_Matrix3x3& vec, bool transpose)
684 {
685         if( GLEW_ARB_fragment_shader &&
686                 GLEW_ARB_vertex_shader &&
687                 GLEW_ARB_shader_objects 
688                 )
689         {
690                 float value[9];
691                 value[0] = (float)vec[0][0]; value[1] = (float)vec[1][0]; value[2] = (float)vec[2][0]; 
692                 value[3] = (float)vec[0][1]; value[4] = (float)vec[1][1]; value[5] = (float)vec[2][1]; 
693                 value[6] = (float)vec[0][2]; value[7] = (float)vec[1][2]; value[8] = (float)vec[2][2];
694                 glUniformMatrix3fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
695         }
696 }
697
698 void BL_Shader::SetUniform(int uniform, const float* val, int len)
699 {
700         if( GLEW_ARB_fragment_shader &&
701                 GLEW_ARB_vertex_shader &&
702                 GLEW_ARB_shader_objects 
703                 )
704         {
705                 if(len == 2) 
706                         glUniform2fvARB(uniform, 1,(GLfloat*)val);
707                 else if (len == 3)
708                         glUniform3fvARB(uniform, 1,(GLfloat*)val);
709                 else if (len == 4)
710                         glUniform4fvARB(uniform, 1,(GLfloat*)val);
711                 else
712                         MT_assert(0);
713         }
714 }
715
716 void BL_Shader::SetUniform(int uniform, const int* val, int len)
717 {
718         if( GLEW_ARB_fragment_shader &&
719                 GLEW_ARB_vertex_shader &&
720                 GLEW_ARB_shader_objects 
721                 )
722         {
723                 if(len == 2) 
724                         glUniform2ivARB(uniform, 1, (GLint*)val);
725                 else if (len == 3)
726                         glUniform3ivARB(uniform, 1, (GLint*)val);
727                 else if (len == 4)
728                         glUniform4ivARB(uniform, 1, (GLint*)val);
729                 else
730                         MT_assert(0);
731         }
732 }
733
734 #ifdef WITH_PYTHON
735
736 PyMethodDef BL_Shader::Methods[] = 
737 {
738         // creation
739         KX_PYMETHODTABLE( BL_Shader, setSource ),
740         KX_PYMETHODTABLE( BL_Shader, delSource ),
741         KX_PYMETHODTABLE( BL_Shader, getVertexProg ),
742         KX_PYMETHODTABLE( BL_Shader, getFragmentProg ),
743         KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ),
744         KX_PYMETHODTABLE( BL_Shader, validate),
745         /// access functions
746         KX_PYMETHODTABLE( BL_Shader, isValid),
747         KX_PYMETHODTABLE( BL_Shader, setUniform1f ),
748         KX_PYMETHODTABLE( BL_Shader, setUniform2f ),
749         KX_PYMETHODTABLE( BL_Shader, setUniform3f ),
750         KX_PYMETHODTABLE( BL_Shader, setUniform4f ),
751         KX_PYMETHODTABLE( BL_Shader, setUniform1i ),
752         KX_PYMETHODTABLE( BL_Shader, setUniform2i ),
753         KX_PYMETHODTABLE( BL_Shader, setUniform3i ),
754         KX_PYMETHODTABLE( BL_Shader, setUniform4i ),
755         KX_PYMETHODTABLE( BL_Shader, setAttrib ),
756
757         KX_PYMETHODTABLE( BL_Shader, setUniformfv ),
758         KX_PYMETHODTABLE( BL_Shader, setUniformiv ),
759         KX_PYMETHODTABLE( BL_Shader, setUniformDef ),
760
761         KX_PYMETHODTABLE( BL_Shader, setSampler  ),
762         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ),
763         KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ),
764
765         {NULL,NULL} //Sentinel
766 };
767
768 PyAttributeDef BL_Shader::Attributes[] = {
769         { NULL }        //Sentinel
770 };
771
772 PyTypeObject BL_Shader::Type = {
773         PyVarObject_HEAD_INIT(NULL, 0)
774         "BL_Shader",
775         sizeof(PyObjectPlus_Proxy),
776         0,
777         py_base_dealloc,
778         0,
779         0,
780         0,
781         0,
782         py_base_repr,
783         0,0,0,0,0,0,0,0,0,
784         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
785         0,0,0,0,0,0,0,
786         Methods,
787         0,
788         0,
789         &PyObjectPlus::Type,
790         0,0,0,0,0,0,
791         py_base_new
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:setSource", &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 PyLong_FromSsize_t( ( mShader !=0 &&  mOk ) );
836 }
837
838 KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" )
839 {
840         return PyUnicode_FromString(vertProg?vertProg:"");
841 }
842
843 KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" )
844 {
845         return PyUnicode_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_SetString(PyExc_TypeError, "shader.validate(): BL_Shader, 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:setSampler", &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:setNumberOfPasses", &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:setUniform1f", &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:setUniform2f", &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:setUniform3f", &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:setUniform4f", &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:setUniform1i", &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:setUniform2i", &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:setUniform3i", &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:setUniform4i", &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:setUniformfv", &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_SetString(PyExc_TypeError, "shader.setUniform4i(name, ix,iy,iz, iw): BL_Shader. 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( uniform_name, (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:setUniformiv", &uniform, &listPtr))
1191                 return NULL;
1192         
1193         int loc = GetUniformLocation(uniform);
1194         
1195         if(loc == -1) {
1196                 PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, first string argument is not a valid uniform value");
1197                 return NULL;
1198         }
1199         
1200         if(!PySequence_Check(listPtr)) {
1201                 PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument is not a sequence");
1202                 return NULL;
1203         }
1204         
1205         unsigned int list_size = PySequence_Size(listPtr);
1206         
1207         for(unsigned int i=0; (i<list_size && i<4); i++)
1208         {
1209                 PyObject *item = PySequence_GetItem(listPtr, i);
1210                 array_data[i] = PyLong_AsSsize_t(item);
1211                 Py_DECREF(item);
1212         }
1213         
1214         if(PyErr_Occurred()) {
1215                 PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, one or more values in the list is not an int");
1216                 return NULL;
1217         }
1218         
1219         /* Sanity checks done! */
1220         
1221         switch(list_size)
1222         {
1223         case 2:
1224                 {
1225                         int array2[2] = { array_data[0],array_data[1]};
1226 #ifdef SORT_UNIFORMS
1227                         SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
1228 #else
1229                         SetUniform(loc, array2, 2);                                             
1230 #endif
1231                         Py_RETURN_NONE;
1232                 } break;
1233         case 3:
1234                 {
1235                         int array3[3] = { array_data[0],array_data[1],array_data[2] };
1236 #ifdef SORT_UNIFORMS
1237                         SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
1238                         
1239 #else
1240                         SetUniform(loc, array3, 3);     
1241 #endif
1242                         Py_RETURN_NONE;
1243                 }break;
1244         case 4:
1245                 {
1246                         int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
1247 #ifdef SORT_UNIFORMS
1248                         SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
1249                         
1250 #else
1251                         SetUniform(loc, array4, 4);     
1252 #endif
1253                         Py_RETURN_NONE;
1254                 }break;
1255         default:
1256                 {
1257                         PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument, invalid list size, expected an int list between 2 and 4");
1258                         return NULL;
1259                 }break;
1260         }
1261         
1262         Py_RETURN_NONE;
1263 }
1264
1265
1266 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 
1267 "setUniformMatrix4(uniform_name, mat-4x4, transpose(row-major=true, col-major=false)" )
1268 {
1269         if(mError) {
1270                 Py_RETURN_NONE;
1271         }
1272
1273         float matr[16] = {
1274                 1,0,0,0,
1275                 0,1,0,0,
1276                 0,0,1,0,
1277                 0,0,0,1
1278         };
1279
1280         const char *uniform="";
1281         PyObject *matrix=0;
1282         int transp=0; // python use column major by default, so no transpose....
1283         
1284         if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix4",&uniform, &matrix,&transp))
1285                 return NULL;
1286
1287         int loc = GetUniformLocation(uniform);
1288         
1289         if(loc == -1) {
1290                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, first string argument is not a valid uniform value");
1291                 return NULL;
1292         }
1293         
1294         MT_Matrix4x4 mat;
1295         
1296         if (!PyMatTo(matrix, mat)) {
1297                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, second argument cannot be converted into a 4x4 matrix");
1298                 return NULL;
1299         }
1300         
1301         /* Sanity checks done! */
1302
1303 #ifdef SORT_UNIFORMS
1304         mat.getValue(matr);
1305         SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) );
1306 #else
1307         SetUniform(loc,mat,(transp!=0));
1308 #endif
1309         Py_RETURN_NONE;
1310 }
1311
1312
1313 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
1314 "setUniformMatrix3(uniform_name, list[3x3], transpose(row-major=true, col-major=false)" )
1315 {
1316         if(mError) {
1317                 Py_RETURN_NONE;
1318         }
1319
1320         float matr[9] = {
1321                 1,0,0,
1322                 0,1,0,
1323                 0,0,1,
1324         };
1325
1326         const char *uniform="";
1327         PyObject *matrix=0;
1328         int transp=0; // python use column major by default, so no transpose....
1329         if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix3",&uniform, &matrix,&transp))
1330                 return NULL;
1331         
1332         int loc = GetUniformLocation(uniform);
1333         
1334         if(loc == -1) {
1335                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, first string argument is not a valid uniform value");
1336                 return NULL;
1337         }
1338         
1339         
1340         MT_Matrix3x3 mat;
1341         
1342         if (!PyMatTo(matrix, mat)) {
1343                 PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, second argument cannot be converted into a 3x3 matrix");
1344                 return NULL;
1345         }
1346         
1347
1348 #ifdef SORT_UNIFORMS
1349         mat.getValue(matr);
1350         SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) );
1351 #else
1352         SetUniform(loc,mat,(transp!=0));
1353 #endif
1354         Py_RETURN_NONE;
1355 }
1356
1357 KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
1358 {
1359         if(mError) {
1360                 Py_RETURN_NONE;
1361         }
1362         
1363         int attr=0;
1364         
1365         if(!PyArg_ParseTuple(args, "i:setAttrib", &attr ))
1366                 return NULL;
1367         
1368         if(mShader==0) {
1369                 PyErr_SetString(PyExc_ValueError, "shader.setAttrib() BL_Shader, invalid shader object");
1370                 return NULL;
1371         }
1372         mAttr=SHD_TANGENT; /* What the heck is going on here - attr is just ignored??? - Campbell */
1373         glUseProgramObjectARB(mShader);
1374         glBindAttribLocationARB(mShader, mAttr, "Tangent");
1375         Py_RETURN_NONE;
1376 }
1377
1378
1379 KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
1380 {
1381         if(mError) {
1382                 Py_RETURN_NONE;
1383         }
1384
1385         const char *uniform="";
1386         int nloc=0;
1387         if(PyArg_ParseTuple(args, "si:setUniformDef",&uniform, &nloc))
1388         {
1389                 int loc = GetUniformLocation(uniform);
1390                 if(loc != -1)
1391                 {
1392                         bool defined = false;
1393                         BL_UniformVecDef::iterator it = mPreDef.begin();
1394                         while(it != mPreDef.end()) {
1395                                 if((*it)->mLoc == loc) {
1396                                         defined = true;
1397                                         break;
1398                                 }
1399                                 it++;
1400                         }
1401                         if(defined)
1402                         {
1403                                 Py_RETURN_NONE;
1404                         }
1405
1406                         BL_DefUniform *uni = new BL_DefUniform();
1407                         uni->mLoc = loc;
1408                         uni->mType = nloc;
1409                         uni->mFlag = 0;
1410                         mPreDef.push_back(uni);
1411                         Py_RETURN_NONE;
1412                 }
1413         }
1414         return NULL;
1415 }
1416
1417 #endif // WITH_PYTHON
1418
1419 // eof