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