Blender V2.61 - r43446

BL_Shader.cpp

Go to the documentation of this file.
00001 
00005 #include "GL/glew.h"
00006 
00007 #include <iostream>
00008 #include "BL_Shader.h"
00009 #include "BL_Material.h"
00010 
00011 #include "MT_assert.h"
00012 #include "MT_Matrix4x4.h"
00013 #include "MT_Matrix3x3.h"
00014 #include "KX_PyMath.h"
00015 #include "MEM_guardedalloc.h"
00016 
00017 #include "RAS_GLExtensionManager.h"
00018 #include "RAS_MeshObject.h"
00019 #include "RAS_IRasterizer.h"
00020 
00021 #define spit(x) std::cout << x << std::endl;
00022 
00023 #define SORT_UNIFORMS 1
00024 #define UNIFORM_MAX_LEN (int)sizeof(float)*16
00025 #define MAX_LOG_LEN 262144 // bounds
00026 
00027 BL_Uniform::BL_Uniform(int data_size)
00028 :   mLoc(-1),
00029     mDirty(true),
00030     mType(UNI_NONE),
00031     mTranspose(0),
00032     mDataLen(data_size)
00033 {
00034 #ifdef SORT_UNIFORMS
00035     MT_assert((int)mDataLen <= UNIFORM_MAX_LEN);
00036     mData = (void*)MEM_mallocN(mDataLen, "shader-uniform-alloc");
00037 #endif
00038 }
00039 
00040 BL_Uniform::~BL_Uniform()
00041 {
00042 #ifdef SORT_UNIFORMS
00043     if(mData) {
00044         MEM_freeN(mData);
00045         mData=0;
00046     }
00047 #endif
00048 }
00049 
00050 void BL_Uniform::Apply(class BL_Shader *shader)
00051 {
00052 #ifdef SORT_UNIFORMS
00053     MT_assert(mType > UNI_NONE && mType < UNI_MAX && mData);
00054 
00055     if(!mDirty) 
00056         return;
00057 
00058     switch(mType)
00059     {
00060     case UNI_FLOAT: {
00061             float *f = (float*)mData;
00062             glUniform1fARB(mLoc,(GLfloat)*f);
00063         }break;
00064     case UNI_INT: {
00065             int *f = (int*)mData;
00066             glUniform1iARB(mLoc, (GLint)*f);
00067         }break;
00068     case UNI_FLOAT2: {
00069             float *f = (float*)mData;
00070             glUniform2fvARB(mLoc,1, (GLfloat*)f);
00071         }break;
00072     case UNI_FLOAT3: {
00073             float *f = (float*)mData;
00074             glUniform3fvARB(mLoc,1,(GLfloat*)f);
00075         }break;
00076     case UNI_FLOAT4: {
00077             float *f = (float*)mData;
00078             glUniform4fvARB(mLoc,1,(GLfloat*)f);
00079         }break;
00080     case UNI_INT2: {
00081             int *f = (int*)mData;
00082             glUniform2ivARB(mLoc,1,(GLint*)f);
00083         }break; 
00084     case UNI_INT3: {
00085             int *f = (int*)mData;
00086             glUniform3ivARB(mLoc,1,(GLint*)f);
00087         }break; 
00088     case UNI_INT4: {
00089             int *f = (int*)mData;
00090             glUniform4ivARB(mLoc,1,(GLint*)f);
00091         }break;
00092     case UNI_MAT4: {
00093             float *f = (float*)mData;
00094             glUniformMatrix4fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f);
00095         }break;
00096     case UNI_MAT3: {
00097             float *f = (float*)mData;
00098             glUniformMatrix3fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f);
00099         }break;
00100     }
00101     mDirty = false;
00102 #endif
00103 }
00104 
00105 void BL_Uniform::SetData(int location, int type,bool transpose)
00106 {
00107 #ifdef SORT_UNIFORMS
00108     mType   = type;
00109     mLoc    = location;
00110     mDirty  = true;
00111 #endif
00112 }
00113 
00114 bool BL_Shader::Ok()const
00115 {
00116     return (mShader !=0 && mOk && mUse);
00117 }
00118 
00119 BL_Shader::BL_Shader()
00120 :   PyObjectPlus(),
00121     mShader(0),
00122     mPass(1),
00123     mOk(0),
00124     mUse(0),
00125     mAttr(0),
00126     vertProg(""),
00127     fragProg(""),
00128     mError(0),
00129     mDirty(true)
00130 {
00131     // if !GLEW_ARB_shader_objects this class will not be used
00132     //for (int i=0; i<MAXTEX; i++) {
00133     //  mSampler[i] = BL_Sampler();
00134     //}
00135 }
00136 
00137 BL_Shader::~BL_Shader()
00138 {
00139     //for (int i=0; i<MAXTEX; i++){
00140     //  if(mSampler[i].mOwn) {
00141     //      if(mSampler[i].mTexture)
00142     //          mSampler[i].mTexture->DeleteTex();
00143     //  }
00144     //}
00145     ClearUniforms();
00146 
00147     if( mShader ) {
00148         glDeleteObjectARB(mShader);
00149         mShader = 0;
00150     }
00151     vertProg    = 0;
00152     fragProg    = 0;
00153     mOk         = 0;
00154     glUseProgramObjectARB(0);
00155 }
00156 
00157 void BL_Shader::ClearUniforms()
00158 {
00159     BL_UniformVec::iterator it = mUniforms.begin();
00160     while(it != mUniforms.end()){
00161         delete (*it);
00162         it++;
00163     }
00164     mUniforms.clear();
00165 
00166     
00167     BL_UniformVecDef::iterator itp = mPreDef.begin();
00168     while(itp != mPreDef.end()) {
00169         delete (*itp);
00170         itp++;
00171     }
00172     mPreDef.clear();
00173 
00174 }
00175 
00176 
00177 BL_Uniform  *BL_Shader::FindUniform(const int location)
00178 {
00179 #ifdef SORT_UNIFORMS
00180     BL_UniformVec::iterator it = mUniforms.begin();
00181     while(it != mUniforms.end()) {
00182         if((*it)->GetLocation() == location)
00183             return (*it);
00184         it++;
00185     }
00186 #endif
00187     return 0;
00188 }
00189 
00190 void BL_Shader::SetUniformfv(int location, int type, float *param,int size, bool transpose)
00191 {
00192 #ifdef SORT_UNIFORMS
00193     BL_Uniform *uni= FindUniform(location);
00194     if(uni) {
00195         memcpy(uni->getData(), param, size);
00196         uni->SetData(location, type, transpose);
00197     }
00198     else {
00199         uni = new BL_Uniform(size);
00200         memcpy(uni->getData(), param, size);
00201 
00202         uni->SetData(location, type, transpose);
00203         mUniforms.push_back(uni);
00204     }
00205     mDirty = true;
00206 #endif
00207 }
00208 
00209 void BL_Shader::SetUniformiv(int location, int type, int *param,int size, bool transpose)
00210 {
00211 #ifdef SORT_UNIFORMS
00212     BL_Uniform *uni= FindUniform(location);
00213     if(uni) {
00214         memcpy(uni->getData(), param, size);
00215         uni->SetData(location, type, transpose);
00216     }
00217     else {
00218         uni = new BL_Uniform(size);
00219         memcpy(uni->getData(), param, size);
00220         uni->SetData(location, type, transpose);
00221         mUniforms.push_back(uni);
00222     }
00223     mDirty = true;
00224 #endif
00225 }
00226 
00227 
00228 void BL_Shader::ApplyShader()
00229 {
00230 #ifdef SORT_UNIFORMS
00231     if(!mDirty) 
00232         return;
00233 
00234     for(unsigned int i=0; i<mUniforms.size(); i++)
00235         mUniforms[i]->Apply(this);
00236 
00237     mDirty = false;
00238 #endif
00239 }
00240 
00241 void BL_Shader::UnloadShader()
00242 {
00243     //
00244 }
00245 
00246 
00247 bool BL_Shader::LinkProgram()
00248 {
00249     int vertlen = 0, fraglen=0, proglen=0;
00250     int vertstatus=0, fragstatus=0, progstatus=0;
00251     unsigned int tmpVert=0, tmpFrag=0, tmpProg=0;
00252     int char_len=0;
00253     char *logInf =0;
00254 
00255     if(mError)
00256         goto programError;
00257 
00258     if(!vertProg || !fragProg){
00259         spit("Invalid GLSL sources");
00260         return false;
00261     }
00262     if( !GLEW_ARB_fragment_shader) {
00263         spit("Fragment shaders not supported");
00264         return false;
00265     }
00266     if( !GLEW_ARB_vertex_shader) {
00267         spit("Vertex shaders not supported");
00268         return false;
00269     }
00270     
00271     // -- vertex shader ------------------
00272     tmpVert = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
00273     glShaderSourceARB(tmpVert, 1, (const char**)&vertProg, 0);
00274     glCompileShaderARB(tmpVert);
00275     glGetObjectParameterivARB(tmpVert, GL_OBJECT_INFO_LOG_LENGTH_ARB,(GLint*) &vertlen);
00276     
00277     // print info if any
00278     if( vertlen > 0 && vertlen < MAX_LOG_LEN){
00279         logInf = (char*)MEM_mallocN(vertlen, "vert-log");
00280         glGetInfoLogARB(tmpVert, vertlen, (GLsizei*)&char_len, logInf);
00281         if(char_len >0) {
00282             spit("---- Vertex Shader Error ----");
00283             spit(logInf);
00284         }
00285         MEM_freeN(logInf);
00286         logInf=0;
00287     }
00288     // check for compile errors
00289     glGetObjectParameterivARB(tmpVert, GL_OBJECT_COMPILE_STATUS_ARB,(GLint*)&vertstatus);
00290     if(!vertstatus) {
00291         spit("---- Vertex shader failed to compile ----");
00292         goto programError;
00293     }
00294 
00295     // -- fragment shader ----------------
00296     tmpFrag = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
00297     glShaderSourceARB(tmpFrag, 1,(const char**)&fragProg, 0);
00298     glCompileShaderARB(tmpFrag);
00299     glGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &fraglen);
00300     if(fraglen >0 && fraglen < MAX_LOG_LEN){
00301         logInf = (char*)MEM_mallocN(fraglen, "frag-log");
00302         glGetInfoLogARB(tmpFrag, fraglen,(GLsizei*) &char_len, logInf);
00303         if(char_len >0) {
00304             spit("---- Fragment Shader Error ----");
00305             spit(logInf);
00306         }
00307         MEM_freeN(logInf);
00308         logInf=0;
00309     }
00310 
00311     glGetObjectParameterivARB(tmpFrag, GL_OBJECT_COMPILE_STATUS_ARB, (GLint*) &fragstatus);
00312     if(!fragstatus){
00313         spit("---- Fragment shader failed to compile ----");
00314         goto programError;
00315     }
00316 
00317     
00318     // -- program ------------------------
00319     //  set compiled vert/frag shader & link
00320     tmpProg = glCreateProgramObjectARB();
00321     glAttachObjectARB(tmpProg, tmpVert);
00322     glAttachObjectARB(tmpProg, tmpFrag);
00323     glLinkProgramARB(tmpProg);
00324     glGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &proglen);
00325     glGetObjectParameterivARB(tmpProg, GL_OBJECT_LINK_STATUS_ARB, (GLint*) &progstatus);
00326     
00327 
00328     if(proglen > 0 && proglen < MAX_LOG_LEN) {
00329         logInf = (char*)MEM_mallocN(proglen, "prog-log");
00330         glGetInfoLogARB(tmpProg, proglen, (GLsizei*)&char_len, logInf);
00331         if(char_len >0) {
00332             spit("---- GLSL Program ----");
00333             spit(logInf);
00334         }
00335         MEM_freeN(logInf);
00336         logInf=0;
00337     }
00338 
00339     if(!progstatus){
00340         spit("---- GLSL program failed to link ----");
00341         goto programError;
00342     }
00343 
00344     // set
00345     mShader = tmpProg;
00346     glDeleteObjectARB(tmpVert);
00347     glDeleteObjectARB(tmpFrag);
00348     mOk     = 1;
00349     mError = 0;
00350     return true;
00351 
00352 programError:
00353     if(tmpVert) {
00354         glDeleteObjectARB(tmpVert);
00355         tmpVert=0;
00356     }
00357     if(tmpFrag) {
00358         glDeleteObjectARB(tmpFrag);
00359         tmpFrag=0;
00360     }
00361 
00362     if(tmpProg) {
00363         glDeleteObjectARB(tmpProg);
00364         tmpProg=0;
00365     }
00366 
00367     mOk     = 0;
00368     mUse    = 0;
00369     mError  = 1;
00370     return false;
00371 }
00372 
00373 const char *BL_Shader::GetVertPtr()
00374 {
00375     return vertProg?vertProg:0;
00376 }
00377 
00378 const char *BL_Shader::GetFragPtr()
00379 {
00380     return fragProg?fragProg:0;
00381 }
00382 
00383 void BL_Shader::SetVertPtr( char *vert )
00384 {
00385     vertProg = vert;
00386 }
00387 
00388 void BL_Shader::SetFragPtr( char *frag )
00389 {
00390     fragProg = frag;
00391 }
00392 
00393 unsigned int BL_Shader::GetProg()
00394 { 
00395     return mShader;
00396 }
00397 //
00398 //const BL_Sampler* BL_Shader::GetSampler(int i)
00399 //{
00400 //  MT_assert(i<=MAXTEX);
00401 //  return &mSampler[i];
00402 //}
00403 
00404 void BL_Shader::SetSampler(int loc, int unit)
00405 {
00406     if( GLEW_ARB_fragment_shader &&
00407         GLEW_ARB_vertex_shader &&
00408         GLEW_ARB_shader_objects 
00409         )
00410     {
00411         glUniform1iARB(loc, unit);
00412     }
00413 }
00414 //
00415 //void BL_Shader::InitializeSampler(int unit, BL_Texture* texture)
00416 //{
00417 //  MT_assert(unit<=MAXTEX);
00418 //  mSampler[unit].mTexture = texture;
00419 //  mSampler[unit].mLoc =-1;
00420 //  mSampler[unit].mOwn = 0;
00421 //}
00422 
00423 void BL_Shader::SetProg(bool enable)
00424 {
00425     if( GLEW_ARB_fragment_shader &&
00426         GLEW_ARB_vertex_shader &&
00427         GLEW_ARB_shader_objects 
00428         )
00429     {
00430         if( mShader != 0 && mOk && enable) {
00431             glUseProgramObjectARB(mShader);
00432         }
00433         else {
00434             glUseProgramObjectARB(0);   
00435         }
00436     }
00437 }
00438 
00439 void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
00440 {
00441     if(!Ok() || !mPreDef.size()) 
00442         return;
00443 
00444     if( GLEW_ARB_fragment_shader &&
00445         GLEW_ARB_vertex_shader &&
00446         GLEW_ARB_shader_objects 
00447         )
00448     {
00449         MT_Matrix4x4 model;
00450         model.setValue(ms.m_OpenGLMatrix);
00451         const MT_Matrix4x4& view = rasty->GetViewMatrix();
00452 
00453         if(mAttr==SHD_TANGENT)
00454             ms.m_mesh->SetMeshModified(true);
00455 
00456         BL_UniformVecDef::iterator it;
00457         for(it = mPreDef.begin(); it!= mPreDef.end(); it++)
00458         {
00459             BL_DefUniform *uni = (*it);
00460             if(uni->mLoc == -1) continue;
00461 
00462             switch (uni->mType)
00463             {
00464                 case MODELMATRIX:
00465                     {
00466                         SetUniform(uni->mLoc, model);
00467                         break;
00468                     }
00469                 case MODELMATRIX_TRANSPOSE:
00470                     {
00471                         SetUniform(uni->mLoc, model, true);
00472                         break;
00473                     }
00474                 case MODELMATRIX_INVERSE:
00475                     {
00476                         model.invert();
00477                         SetUniform(uni->mLoc, model);
00478                         break;
00479                     }
00480                 case MODELMATRIX_INVERSETRANSPOSE:
00481                     {
00482                         model.invert();
00483                         SetUniform(uni->mLoc, model, true);
00484                         break;
00485                     }
00486                 case MODELVIEWMATRIX:
00487                     {
00488                         SetUniform(uni->mLoc, view*model);
00489                         break;
00490                     }
00491 
00492                 case MODELVIEWMATRIX_TRANSPOSE:
00493                     {
00494                         MT_Matrix4x4 mat(view*model);
00495                         SetUniform(uni->mLoc, mat, true);
00496                         break;
00497                     }
00498                 case MODELVIEWMATRIX_INVERSE:
00499                     {
00500                         MT_Matrix4x4 mat(view*model);
00501                         mat.invert();
00502                         SetUniform(uni->mLoc, mat);
00503                         break;
00504                     }
00505                 case MODELVIEWMATRIX_INVERSETRANSPOSE:
00506                     {
00507                         MT_Matrix4x4 mat(view*model);
00508                         mat.invert();
00509                         SetUniform(uni->mLoc, mat, true);
00510                         break;
00511                     }
00512                 case CAM_POS:
00513                     {
00514                         MT_Point3 pos(rasty->GetCameraPosition());
00515                         SetUniform(uni->mLoc, pos);
00516                         break;
00517                     }
00518                 case VIEWMATRIX:
00519                     {
00520                         SetUniform(uni->mLoc, view);
00521                         break;
00522                     }
00523                 case VIEWMATRIX_TRANSPOSE:
00524                     {
00525                         SetUniform(uni->mLoc, view, true);
00526                         break;
00527                     }
00528                 case VIEWMATRIX_INVERSE:
00529                     {
00530                         MT_Matrix4x4 viewinv = view;
00531                         viewinv.invert();
00532                         SetUniform(uni->mLoc, view);
00533                         break;
00534                     }
00535                 case VIEWMATRIX_INVERSETRANSPOSE:
00536                     {
00537                         MT_Matrix4x4 viewinv = view;
00538                         viewinv.invert();
00539                         SetUniform(uni->mLoc, view, true);
00540                         break;
00541                     }
00542                 case CONSTANT_TIMER:
00543                     {
00544                         SetUniform(uni->mLoc, (float)rasty->GetTime());
00545                         break;
00546                     }
00547                 default:
00548                     break;
00549             }
00550         }
00551     }
00552 }
00553 
00554 
00555 int BL_Shader::GetAttribLocation(const STR_String& name)
00556 {
00557     if( GLEW_ARB_fragment_shader &&
00558         GLEW_ARB_vertex_shader &&
00559         GLEW_ARB_shader_objects 
00560         )
00561     {
00562         return glGetAttribLocationARB(mShader, name.ReadPtr());
00563     }
00564 
00565     return -1;
00566 }
00567 
00568 void BL_Shader::BindAttribute(const STR_String& attr, int loc)
00569 {
00570     if( GLEW_ARB_fragment_shader &&
00571         GLEW_ARB_vertex_shader &&
00572         GLEW_ARB_shader_objects 
00573         )
00574     {
00575         glBindAttribLocationARB(mShader, loc, attr.ReadPtr());
00576     }
00577 }
00578 
00579 int BL_Shader::GetUniformLocation(const STR_String& name)
00580 {
00581     if( GLEW_ARB_fragment_shader &&
00582         GLEW_ARB_vertex_shader &&
00583         GLEW_ARB_shader_objects 
00584         )
00585     {
00586         MT_assert(mShader!=0);
00587         int location = glGetUniformLocationARB(mShader, name.ReadPtr());
00588         if(location == -1)
00589             spit("Invalid uniform value: " << name.ReadPtr() << ".");
00590         return location;
00591     }
00592 
00593     return -1;
00594 }
00595 
00596 void BL_Shader::SetUniform(int uniform, const MT_Tuple2& vec)
00597 {
00598     if( GLEW_ARB_fragment_shader &&
00599         GLEW_ARB_vertex_shader &&
00600         GLEW_ARB_shader_objects 
00601         )
00602     {
00603         float value[2];
00604         vec.getValue(value);
00605         glUniform2fvARB(uniform, 1, value);
00606     }
00607 
00608 }
00609 
00610 void BL_Shader::SetUniform(int uniform, const MT_Tuple3& vec)
00611 {
00612     if( GLEW_ARB_fragment_shader &&
00613         GLEW_ARB_vertex_shader &&
00614         GLEW_ARB_shader_objects 
00615         )
00616     {   
00617         float value[3];
00618         vec.getValue(value);
00619         glUniform3fvARB(uniform, 1, value);
00620     }
00621 }
00622 
00623 void BL_Shader::SetUniform(int uniform, const MT_Tuple4& vec)
00624 {
00625     if( GLEW_ARB_fragment_shader &&
00626         GLEW_ARB_vertex_shader &&
00627         GLEW_ARB_shader_objects 
00628         )
00629     {
00630         float value[4];
00631         vec.getValue(value);
00632         glUniform4fvARB(uniform, 1, value);
00633     }
00634 }
00635 
00636 void BL_Shader::SetUniform(int uniform, const unsigned int& val)
00637 {
00638     if( GLEW_ARB_fragment_shader &&
00639         GLEW_ARB_vertex_shader &&
00640         GLEW_ARB_shader_objects 
00641         )
00642     {
00643         glUniform1iARB(uniform, val);
00644     }
00645 }
00646 
00647 void BL_Shader::SetUniform(int uniform, const int val)
00648 {
00649     if( GLEW_ARB_fragment_shader &&
00650         GLEW_ARB_vertex_shader &&
00651         GLEW_ARB_shader_objects 
00652         )
00653     {
00654         glUniform1iARB(uniform, val);
00655     }
00656 }
00657 
00658 void BL_Shader::SetUniform(int uniform, const float& val)
00659 {
00660     if( GLEW_ARB_fragment_shader &&
00661         GLEW_ARB_vertex_shader &&
00662         GLEW_ARB_shader_objects 
00663         )
00664     {
00665         glUniform1fARB(uniform, val);
00666     }
00667 }
00668 
00669 void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose)
00670 {
00671     if( GLEW_ARB_fragment_shader &&
00672         GLEW_ARB_vertex_shader &&
00673         GLEW_ARB_shader_objects 
00674         )
00675     {
00676         float value[16];
00677         // note: getValue gives back column major as needed by OpenGL
00678         vec.getValue(value);
00679         glUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
00680     }
00681 }
00682 
00683 void BL_Shader::SetUniform(int uniform, const MT_Matrix3x3& vec, bool transpose)
00684 {
00685     if( GLEW_ARB_fragment_shader &&
00686         GLEW_ARB_vertex_shader &&
00687         GLEW_ARB_shader_objects 
00688         )
00689     {
00690         float value[9];
00691         value[0] = (float)vec[0][0]; value[1] = (float)vec[1][0]; value[2] = (float)vec[2][0]; 
00692         value[3] = (float)vec[0][1]; value[4] = (float)vec[1][1]; value[5] = (float)vec[2][1]; 
00693         value[6] = (float)vec[0][2]; value[7] = (float)vec[1][2]; value[8] = (float)vec[2][2];
00694         glUniformMatrix3fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
00695     }
00696 }
00697 
00698 void BL_Shader::SetUniform(int uniform, const float* val, int len)
00699 {
00700     if( GLEW_ARB_fragment_shader &&
00701         GLEW_ARB_vertex_shader &&
00702         GLEW_ARB_shader_objects 
00703         )
00704     {
00705         if(len == 2) 
00706             glUniform2fvARB(uniform, 1,(GLfloat*)val);
00707         else if (len == 3)
00708             glUniform3fvARB(uniform, 1,(GLfloat*)val);
00709         else if (len == 4)
00710             glUniform4fvARB(uniform, 1,(GLfloat*)val);
00711         else
00712             MT_assert(0);
00713     }
00714 }
00715 
00716 void BL_Shader::SetUniform(int uniform, const int* val, int len)
00717 {
00718     if( GLEW_ARB_fragment_shader &&
00719         GLEW_ARB_vertex_shader &&
00720         GLEW_ARB_shader_objects 
00721         )
00722     {
00723         if(len == 2) 
00724             glUniform2ivARB(uniform, 1, (GLint*)val);
00725         else if (len == 3)
00726             glUniform3ivARB(uniform, 1, (GLint*)val);
00727         else if (len == 4)
00728             glUniform4ivARB(uniform, 1, (GLint*)val);
00729         else
00730             MT_assert(0);
00731     }
00732 }
00733 
00734 #ifdef WITH_PYTHON
00735 
00736 PyMethodDef BL_Shader::Methods[] = 
00737 {
00738     // creation
00739     KX_PYMETHODTABLE( BL_Shader, setSource ),
00740     KX_PYMETHODTABLE( BL_Shader, delSource ),
00741     KX_PYMETHODTABLE( BL_Shader, getVertexProg ),
00742     KX_PYMETHODTABLE( BL_Shader, getFragmentProg ),
00743     KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ),
00744     KX_PYMETHODTABLE( BL_Shader, validate),
00746     KX_PYMETHODTABLE( BL_Shader, isValid),
00747     KX_PYMETHODTABLE( BL_Shader, setUniform1f ),
00748     KX_PYMETHODTABLE( BL_Shader, setUniform2f ),
00749     KX_PYMETHODTABLE( BL_Shader, setUniform3f ),
00750     KX_PYMETHODTABLE( BL_Shader, setUniform4f ),
00751     KX_PYMETHODTABLE( BL_Shader, setUniform1i ),
00752     KX_PYMETHODTABLE( BL_Shader, setUniform2i ),
00753     KX_PYMETHODTABLE( BL_Shader, setUniform3i ),
00754     KX_PYMETHODTABLE( BL_Shader, setUniform4i ),
00755     KX_PYMETHODTABLE( BL_Shader, setAttrib ),
00756 
00757     KX_PYMETHODTABLE( BL_Shader, setUniformfv ),
00758     KX_PYMETHODTABLE( BL_Shader, setUniformiv ),
00759     KX_PYMETHODTABLE( BL_Shader, setUniformDef ),
00760 
00761     KX_PYMETHODTABLE( BL_Shader, setSampler  ),
00762     KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ),
00763     KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ),
00764 
00765     {NULL,NULL} //Sentinel
00766 };
00767 
00768 PyAttributeDef BL_Shader::Attributes[] = {
00769     { NULL }    //Sentinel
00770 };
00771 
00772 PyTypeObject BL_Shader::Type = {
00773     PyVarObject_HEAD_INIT(NULL, 0)
00774     "BL_Shader",
00775     sizeof(PyObjectPlus_Proxy),
00776     0,
00777     py_base_dealloc,
00778     0,
00779     0,
00780     0,
00781     0,
00782     py_base_repr,
00783     0,0,0,0,0,0,0,0,0,
00784     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
00785     0,0,0,0,0,0,0,
00786     Methods,
00787     0,
00788     0,
00789     &PyObjectPlus::Type,
00790     0,0,0,0,0,0,
00791     py_base_new
00792 };
00793 
00794 KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" )
00795 {
00796     if(mShader !=0 && mOk  )
00797     {
00798         // already set...
00799         Py_RETURN_NONE;
00800     }
00801     char *v,*f;
00802     int apply=0;
00803     if( PyArg_ParseTuple(args, "ssi:setSource", &v, &f, &apply) )
00804     {
00805         vertProg = v;
00806         fragProg = f;
00807         if( LinkProgram() ) {
00808             glUseProgramObjectARB( mShader );
00809             mUse = apply!=0;
00810             Py_RETURN_NONE;
00811         }
00812         vertProg = 0;
00813         fragProg = 0;
00814         mUse = 0;
00815         Py_RETURN_NONE;
00816     }
00817     return NULL;
00818 }
00819 
00820 
00821 KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" )
00822 {
00823     ClearUniforms();
00824     glUseProgramObjectARB(0);
00825 
00826     glDeleteObjectARB(mShader);
00827     mShader     = 0;
00828     mOk         = 0;
00829     mUse        = 0;
00830     Py_RETURN_NONE;
00831 }
00832 
00833 KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" )
00834 {
00835     return PyLong_FromSsize_t( ( mShader !=0 &&  mOk ) );
00836 }
00837 
00838 KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" )
00839 {
00840     return PyUnicode_FromString(vertProg?vertProg:"");
00841 }
00842 
00843 KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" )
00844 {
00845     return PyUnicode_FromString(fragProg?fragProg:"");
00846 }
00847 
00848 KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()")
00849 {
00850     if(mError) {
00851         Py_RETURN_NONE;
00852     }
00853     if(mShader==0) {
00854         PyErr_SetString(PyExc_TypeError, "shader.validate(): BL_Shader, invalid shader object");
00855         return NULL;
00856     }
00857     int stat = 0;
00858     glValidateProgramARB(mShader);
00859     glGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB,(GLint*) &stat);
00860 
00861 
00862     if(stat > 0 && stat < MAX_LOG_LEN) {
00863         int char_len=0;
00864         char *logInf = (char*)MEM_mallocN(stat, "validate-log");
00865 
00866         glGetInfoLogARB(mShader, stat,(GLsizei*) &char_len, logInf);
00867         if(char_len >0) {
00868             spit("---- GLSL Validation ----");
00869             spit(logInf);
00870         }
00871         MEM_freeN(logInf);
00872         logInf=0;
00873     }
00874     Py_RETURN_NONE;
00875 }
00876 
00877 
00878 KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
00879 {
00880     if(mError) {
00881         Py_RETURN_NONE;
00882     }
00883 
00884     const char *uniform="";
00885     int index=-1;
00886     if(PyArg_ParseTuple(args, "si:setSampler", &uniform, &index)) 
00887     {
00888         int loc = GetUniformLocation(uniform);
00889         if(loc != -1) {
00890             if(index >= MAXTEX || index < 0)
00891                 spit("Invalid texture sample index: " << index);
00892 
00893 #ifdef SORT_UNIFORMS
00894             SetUniformiv(loc, BL_Uniform::UNI_INT, &index, (sizeof(int)) );
00895 #else
00896             SetUniform(loc, index);
00897 #endif
00898             //if(index <= MAXTEX)
00899             //  mSampler[index].mLoc = loc;
00900             //else
00901             //  spit("Invalid texture sample index: " << index);
00902         }
00903         Py_RETURN_NONE;
00904     }
00905     return NULL;
00906 }
00907 
00908 KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" )
00909 {
00910     int pass = 1;
00911     if(!PyArg_ParseTuple(args, "i:setNumberOfPasses", &pass))
00912         return NULL;
00913 
00914     mPass = 1;
00915     Py_RETURN_NONE;
00916 }
00917 
00919 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" )
00920 {
00921     if(mError) {
00922         Py_RETURN_NONE;
00923     }
00924 
00925     const char *uniform="";
00926     float value=0;
00927     if(PyArg_ParseTuple(args, "sf:setUniform1f", &uniform, &value ))
00928     {
00929         int loc = GetUniformLocation(uniform);
00930         if(loc != -1)
00931         {
00932 #ifdef SORT_UNIFORMS
00933             SetUniformfv(loc, BL_Uniform::UNI_FLOAT, &value, sizeof(float));
00934 #else           
00935             SetUniform( loc, (float)value );
00936 #endif
00937         }
00938         Py_RETURN_NONE;
00939     }
00940     return NULL;
00941 }
00942 
00943 
00944 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
00945 {
00946     if(mError) {
00947         Py_RETURN_NONE;
00948     }
00949     const char *uniform="";
00950     float array[2]={ 0,0 };
00951     if(PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] ))
00952     {
00953         int loc = GetUniformLocation(uniform);
00954         if(loc != -1)
00955         {
00956 #ifdef SORT_UNIFORMS
00957             SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array, (sizeof(float)*2) );
00958 #else
00959             SetUniform(loc, array, 2);
00960 #endif
00961         }
00962         Py_RETURN_NONE;
00963     }
00964     return NULL;
00965 }
00966 
00967 
00968 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
00969 {
00970     if(mError) {
00971         Py_RETURN_NONE;
00972     }
00973     const char *uniform="";
00974     float array[3]={0,0,0};
00975     if(PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2]))
00976     {
00977         int loc = GetUniformLocation(uniform);
00978         if(loc != -1)
00979         {
00980 #ifdef SORT_UNIFORMS
00981             SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array, (sizeof(float)*3) );
00982 #else
00983             SetUniform(loc, array, 3);
00984 #endif
00985         }
00986         Py_RETURN_NONE;
00987 
00988     }
00989     return NULL;
00990 }
00991 
00992 
00993 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
00994 {
00995     if(mError) {
00996         Py_RETURN_NONE;
00997     }
00998     const char *uniform="";
00999     float array[4]={0,0,0,0};
01000     if(PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3]))
01001     {
01002         int loc = GetUniformLocation(uniform);
01003         if(loc != -1)
01004         {
01005 #ifdef SORT_UNIFORMS
01006             SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array, (sizeof(float)*4) );
01007 #else
01008             SetUniform(loc, array, 4);
01009 #endif
01010         }
01011         Py_RETURN_NONE;
01012     }
01013     return NULL;
01014 }
01015 
01016 
01017 KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
01018 {
01019     if(mError) {
01020         Py_RETURN_NONE;
01021     }
01022     const char *uniform="";
01023     int value=0;
01024     if(PyArg_ParseTuple(args, "si:setUniform1i", &uniform, &value ))
01025     {
01026         int loc = GetUniformLocation(uniform);
01027         if(loc != -1)
01028         {
01029 #ifdef SORT_UNIFORMS
01030             SetUniformiv(loc, BL_Uniform::UNI_INT, &value, sizeof(int));
01031 #else
01032             SetUniform(loc, (int)value);
01033 #endif
01034         }
01035         Py_RETURN_NONE;
01036     }
01037     return NULL;
01038 }
01039 
01040 
01041 KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
01042 {
01043     if(mError) {
01044         Py_RETURN_NONE;
01045     }
01046     const char *uniform="";
01047     int array[2]={ 0,0 };
01048     if(PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] ))
01049     {
01050         int loc = GetUniformLocation(uniform);
01051         if(loc != -1)
01052         {
01053 #ifdef SORT_UNIFORMS
01054             SetUniformiv(loc, BL_Uniform::UNI_INT2, array, sizeof(int)*2);
01055 #else
01056             SetUniform(loc, array, 2);
01057 #endif
01058         }
01059         Py_RETURN_NONE;
01060     }
01061     return NULL;
01062 }
01063 
01064 
01065 KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
01066 {
01067     if(mError) {
01068         Py_RETURN_NONE;
01069     }
01070 
01071     const char *uniform="";
01072     int array[3]={0,0,0};
01073     if(PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2]))
01074     {
01075         int loc = GetUniformLocation(uniform);
01076         if(loc != -1)
01077         {
01078 #ifdef SORT_UNIFORMS
01079             SetUniformiv(loc, BL_Uniform::UNI_INT3, array, sizeof(int)*3);
01080 #else
01081             SetUniform(loc, array, 3);
01082 #endif
01083         }
01084         Py_RETURN_NONE;
01085     }
01086     return NULL;
01087 }
01088 
01089 KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
01090 {
01091     if(mError) {
01092         Py_RETURN_NONE;
01093     }
01094     const char *uniform="";
01095     int array[4]={0,0,0, 0};
01096     if(PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] ))
01097     {
01098         int loc = GetUniformLocation(uniform);
01099         if(loc != -1)
01100         {
01101 #ifdef SORT_UNIFORMS
01102             SetUniformiv(loc, BL_Uniform::UNI_INT4, array, sizeof(int)*4);
01103 #else
01104             SetUniform(loc, array, 4);
01105 #endif
01106         }
01107         Py_RETURN_NONE;
01108     }
01109     return NULL;
01110 }
01111 
01112 KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )")
01113 {
01114     if(mError) {
01115         Py_RETURN_NONE;
01116     }
01117     const char *uniform = "";
01118     PyObject *listPtr =0;
01119     float array_data[4] = {0.f,0.f,0.f,0.f};
01120 
01121     if(PyArg_ParseTuple(args, "sO:setUniformfv", &uniform, &listPtr))
01122     {
01123         int loc = GetUniformLocation(uniform);
01124         if(loc != -1)
01125         {
01126             if(PySequence_Check(listPtr))
01127             {
01128                 unsigned int list_size = PySequence_Size(listPtr);
01129                 
01130                 for(unsigned int i=0; (i<list_size && i<4); i++)
01131                 {
01132                     PyObject *item = PySequence_GetItem(listPtr, i);
01133                     array_data[i] = (float)PyFloat_AsDouble(item);
01134                     Py_DECREF(item);
01135                 }
01136 
01137                 switch(list_size)
01138                 {
01139                 case 2:
01140                     {
01141                         float array2[2] = { array_data[0],array_data[1] };
01142 #ifdef SORT_UNIFORMS
01143                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array2, sizeof(float)*2);
01144 #else
01145                         SetUniform(loc, array2, 2);                     
01146 #endif
01147                         Py_RETURN_NONE;
01148                     } break;
01149                 case 3:
01150                     {
01151                         float array3[3] = { array_data[0],array_data[1],array_data[2] };
01152 #ifdef SORT_UNIFORMS
01153                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array3, sizeof(float)*3);
01154 #else
01155                         SetUniform(loc, array3, 3); 
01156 #endif
01157                         Py_RETURN_NONE;
01158                     }break;
01159                 case 4:
01160                     {
01161                         float array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
01162 #ifdef SORT_UNIFORMS
01163                         SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array4, sizeof(float)*4);
01164 #else
01165                         SetUniform(loc, array4, 4); 
01166 #endif
01167                         Py_RETURN_NONE;
01168                     }break;
01169                 default:
01170                     {
01171                         PyErr_SetString(PyExc_TypeError, "shader.setUniform4i(name, ix,iy,iz, iw): BL_Shader. invalid list size");
01172                         return NULL;
01173                     }break;
01174                 }
01175             }
01176         }
01177     }
01178     return NULL;
01179 }
01180 
01181 KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( uniform_name, (list2 or list3 or list4) )")
01182 {
01183     if(mError) {
01184         Py_RETURN_NONE;
01185     }
01186     const char *uniform = "";
01187     PyObject *listPtr =0;
01188     int array_data[4] = {0,0,0,0};
01189 
01190     if(!PyArg_ParseTuple(args, "sO:setUniformiv", &uniform, &listPtr))
01191         return NULL;
01192     
01193     int loc = GetUniformLocation(uniform);
01194     
01195     if(loc == -1) {
01196         PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, first string argument is not a valid uniform value");
01197         return NULL;
01198     }
01199     
01200     if(!PySequence_Check(listPtr)) {
01201         PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument is not a sequence");
01202         return NULL;
01203     }
01204     
01205     unsigned int list_size = PySequence_Size(listPtr);
01206     
01207     for(unsigned int i=0; (i<list_size && i<4); i++)
01208     {
01209         PyObject *item = PySequence_GetItem(listPtr, i);
01210         array_data[i] = PyLong_AsSsize_t(item);
01211         Py_DECREF(item);
01212     }
01213     
01214     if(PyErr_Occurred()) {
01215         PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, one or more values in the list is not an int");
01216         return NULL;
01217     }
01218     
01219     /* Sanity checks done! */
01220     
01221     switch(list_size)
01222     {
01223     case 2:
01224         {
01225             int array2[2] = { array_data[0],array_data[1]};
01226 #ifdef SORT_UNIFORMS
01227             SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
01228 #else
01229             SetUniform(loc, array2, 2);                     
01230 #endif
01231             Py_RETURN_NONE;
01232         } break;
01233     case 3:
01234         {
01235             int array3[3] = { array_data[0],array_data[1],array_data[2] };
01236 #ifdef SORT_UNIFORMS
01237             SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
01238             
01239 #else
01240             SetUniform(loc, array3, 3); 
01241 #endif
01242             Py_RETURN_NONE;
01243         }break;
01244     case 4:
01245         {
01246             int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
01247 #ifdef SORT_UNIFORMS
01248             SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
01249             
01250 #else
01251             SetUniform(loc, array4, 4); 
01252 #endif
01253             Py_RETURN_NONE;
01254         }break;
01255     default:
01256         {
01257             PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument, invalid list size, expected an int list between 2 and 4");
01258             return NULL;
01259         }break;
01260     }
01261     
01262     Py_RETURN_NONE;
01263 }
01264 
01265 
01266 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 
01267 "setUniformMatrix4(uniform_name, mat-4x4, transpose(row-major=true, col-major=false)" )
01268 {
01269     if(mError) {
01270         Py_RETURN_NONE;
01271     }
01272 
01273     float matr[16] = {
01274         1,0,0,0,
01275         0,1,0,0,
01276         0,0,1,0,
01277         0,0,0,1
01278     };
01279 
01280     const char *uniform="";
01281     PyObject *matrix=0;
01282     int transp=0; // python use column major by default, so no transpose....
01283     
01284     if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix4",&uniform, &matrix,&transp))
01285         return NULL;
01286 
01287     int loc = GetUniformLocation(uniform);
01288     
01289     if(loc == -1) {
01290         PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, first string argument is not a valid uniform value");
01291         return NULL;
01292     }
01293     
01294     MT_Matrix4x4 mat;
01295     
01296     if (!PyMatTo(matrix, mat)) {
01297         PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix4(...): BL_Shader, second argument cannot be converted into a 4x4 matrix");
01298         return NULL;
01299     }
01300     
01301     /* Sanity checks done! */
01302 
01303 #ifdef SORT_UNIFORMS
01304     mat.getValue(matr);
01305     SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) );
01306 #else
01307     SetUniform(loc,mat,(transp!=0));
01308 #endif
01309     Py_RETURN_NONE;
01310 }
01311 
01312 
01313 KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
01314 "setUniformMatrix3(uniform_name, list[3x3], transpose(row-major=true, col-major=false)" )
01315 {
01316     if(mError) {
01317         Py_RETURN_NONE;
01318     }
01319 
01320     float matr[9] = {
01321         1,0,0,
01322         0,1,0,
01323         0,0,1,
01324     };
01325 
01326     const char *uniform="";
01327     PyObject *matrix=0;
01328     int transp=0; // python use column major by default, so no transpose....
01329     if(!PyArg_ParseTuple(args, "sO|i:setUniformMatrix3",&uniform, &matrix,&transp))
01330         return NULL;
01331     
01332     int loc = GetUniformLocation(uniform);
01333     
01334     if(loc == -1) {
01335         PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, first string argument is not a valid uniform value");
01336         return NULL;
01337     }
01338     
01339     
01340     MT_Matrix3x3 mat;
01341     
01342     if (!PyMatTo(matrix, mat)) {
01343         PyErr_SetString(PyExc_TypeError, "shader.setUniformMatrix3(...): BL_Shader, second argument cannot be converted into a 3x3 matrix");
01344         return NULL;
01345     }
01346     
01347 
01348 #ifdef SORT_UNIFORMS
01349     mat.getValue(matr);
01350     SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) );
01351 #else
01352     SetUniform(loc,mat,(transp!=0));
01353 #endif
01354     Py_RETURN_NONE;
01355 }
01356 
01357 KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
01358 {
01359     if(mError) {
01360         Py_RETURN_NONE;
01361     }
01362     
01363     int attr=0;
01364     
01365     if(!PyArg_ParseTuple(args, "i:setAttrib", &attr))
01366         return NULL;
01367 
01368     attr= SHD_TANGENT; /* user input is ignored for now, there is only 1 attr */
01369 
01370     if(mShader==0) {
01371         PyErr_SetString(PyExc_ValueError, "shader.setAttrib() BL_Shader, invalid shader object");
01372         return NULL;
01373     }
01374 
01375     mAttr= attr;
01376     glUseProgramObjectARB(mShader);
01377     glBindAttribLocationARB(mShader, mAttr, "Tangent");
01378     Py_RETURN_NONE;
01379 }
01380 
01381 
01382 KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
01383 {
01384     if(mError) {
01385         Py_RETURN_NONE;
01386     }
01387 
01388     const char *uniform="";
01389     int nloc=0;
01390     if(PyArg_ParseTuple(args, "si:setUniformDef",&uniform, &nloc))
01391     {
01392         int loc = GetUniformLocation(uniform);
01393         if(loc != -1)
01394         {
01395             bool defined = false;
01396             BL_UniformVecDef::iterator it = mPreDef.begin();
01397             while(it != mPreDef.end()) {
01398                 if((*it)->mLoc == loc) {
01399                     defined = true;
01400                     break;
01401                 }
01402                 it++;
01403             }
01404             if(defined)
01405             {
01406                 Py_RETURN_NONE;
01407             }
01408 
01409             BL_DefUniform *uni = new BL_DefUniform();
01410             uni->mLoc = loc;
01411             uni->mType = nloc;
01412             uni->mFlag = 0;
01413             mPreDef.push_back(uni);
01414             Py_RETURN_NONE;
01415         }
01416     }
01417     return NULL;
01418 }
01419 
01420 #endif // WITH_PYTHON
01421 
01422 // eof