// ------------------------------------ #ifdef WIN32 #include #endif // WIN32 #ifdef __APPLE__ #define GL_GLEXT_LEGACY 1 #include #include #else #include #include #endif #include #include "BL_Shader.h" #include "BL_Material.h" #include "MT_assert.h" #include "MT_Matrix4x4.h" #include "MT_Matrix3x3.h" #include "KX_PyMath.h" #include "MEM_guardedalloc.h" #include "RAS_GLExtensionManager.h" //using namespace bgl; #define spit(x) std::cout << x << std::endl; const bool BL_Shader::Ok()const { return (mShader !=0 && mOk && mUse); } BL_Shader::BL_Shader(PyTypeObject *T) : PyObjectPlus(T), mShader(0), mVert(0), mFrag(0), mPass(1), mOk(0), mUse(0), vertProg(""), fragProg("") { // if !RAS_EXT_support._ARB_shader_objects this class will not be used for (int i=0; i 0 && !PrintInfo(vertlen,tmpVert, "Vertex Shader") ){ spit("Vertex shader failed"); bgl::blDeleteObjectARB(tmpVert); bgl::blDeleteObjectARB(tmpFrag); bgl::blDeleteObjectARB(tmpProg); mOk = 0; return false; } // set/compile fragment shader bgl::blShaderSourceARB(tmpFrag, 1,(const char**)&fragProg, 0); bgl::blCompileShaderARB(tmpFrag); bgl::blGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, &fraglen); if(fraglen >0 && !PrintInfo(fraglen,tmpFrag, "Fragment Shader") ){ spit("Fragment shader failed"); bgl::blDeleteObjectARB(tmpVert); bgl::blDeleteObjectARB(tmpFrag); bgl::blDeleteObjectARB(tmpProg); mOk = 0; return false; } // set compiled vert/frag shader & link bgl::blAttachObjectARB(tmpProg, tmpVert); bgl::blAttachObjectARB(tmpProg, tmpFrag); bgl::blLinkProgramARB(tmpProg); bgl::blGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, &proglen); if(proglen > 0){ PrintInfo(proglen,tmpProg, "GLSL Shader"); } else{ spit("Program failed"); bgl::blDeleteObjectARB(tmpVert); bgl::blDeleteObjectARB(tmpFrag); bgl::blDeleteObjectARB(tmpProg); mOk = 0; return false; } // set mShader = tmpProg; mVert = tmpVert; mFrag = tmpFrag; mOk = 1; return true; #else return false; #endif//GL_ARB_shader_objects } bool BL_Shader::PrintInfo(int len, unsigned int handle, const char *type) { #ifdef GL_ARB_shader_objects int numchars=0; char *log = (char*)MEM_mallocN(sizeof(char)*len, "print_log"); if(!log) { spit("BL_Shader::PrintInfo() MEM_mallocN failed"); return false; } bgl::blGetInfoLogARB(handle, len, &numchars, log); if(numchars >0){ spit(type); spit(log); MEM_freeN(log); log=0; return false; } MEM_freeN(log); log=0; return true; #else return false #endif//GL_ARB_shader_objects } char *BL_Shader::GetVertPtr() { return vertProg?vertProg:0; } char *BL_Shader::GetFragPtr() { return fragProg?fragProg:0; } void BL_Shader::SetVertPtr( char *vert ) { vertProg = vert; } void BL_Shader::SetFragPtr( char *frag ) { fragProg = frag; } unsigned int BL_Shader::GetProg() { return mShader; } unsigned int BL_Shader::GetVertexShader() { return mVert; } unsigned int BL_Shader::GetFragmentShader() { return mFrag; } const uSampler* BL_Shader::getSampler(int i) { MT_assert(i<=MAXTEX); return &mSampler[i]; } void BL_Shader::InitializeSampler( int type, int unit, int pass, unsigned int texture) { MT_assert(unit<=MAXTEX); mSampler[unit].glTexture = texture; mSampler[unit].loc =-1; mSampler[unit].pass=0; mSampler[unit].type=type; mSampler[unit].unit=unit; } PyObject* BL_Shader::_getattr(const STR_String& attr) { _getattr_up(PyObjectPlus); } PyMethodDef BL_Shader::Methods[] = { // creation KX_PYMETHODTABLE( BL_Shader, setSource ), KX_PYMETHODTABLE( BL_Shader, delSource ), KX_PYMETHODTABLE( BL_Shader, getVertexProg ), KX_PYMETHODTABLE( BL_Shader, getFragmentProg ), KX_PYMETHODTABLE( BL_Shader, setNumberOfPasses ), KX_PYMETHODTABLE( BL_Shader, validate), /// access functions KX_PYMETHODTABLE( BL_Shader, isValid), KX_PYMETHODTABLE( BL_Shader, setUniform1f ), KX_PYMETHODTABLE( BL_Shader, setUniform2f ), KX_PYMETHODTABLE( BL_Shader, setUniform3f ), KX_PYMETHODTABLE( BL_Shader, setUniform4f ), KX_PYMETHODTABLE( BL_Shader, setUniform1i ), KX_PYMETHODTABLE( BL_Shader, setUniform2i ), KX_PYMETHODTABLE( BL_Shader, setUniform3i ), KX_PYMETHODTABLE( BL_Shader, setUniform4i ), KX_PYMETHODTABLE( BL_Shader, setUniformfv ), KX_PYMETHODTABLE( BL_Shader, setUniformiv ), KX_PYMETHODTABLE( BL_Shader, setSampler ), KX_PYMETHODTABLE( BL_Shader, setUniformMatrix4 ), KX_PYMETHODTABLE( BL_Shader, setUniformMatrix3 ), {NULL,NULL} //Sentinel }; PyTypeObject BL_Shader::Type = { PyObject_HEAD_INIT(&PyType_Type) 0, "BL_Shader", sizeof(BL_Shader), 0, PyDestructor, 0, __getattr, __setattr, 0, __repr, 0 }; PyParentObject BL_Shader::Parents[] = { &PyObjectPlus::Type, &BL_Shader::Type, NULL }; KX_PYMETHODDEF_DOC( BL_Shader, setSource," setSource(vertexProgram, fragmentProgram)" ) { #ifdef GL_ARB_shader_objects if(mShader !=0 && mOk ) { // already set... Py_Return; } char *v,*f; int apply=0; if( PyArg_ParseTuple(args, "ssi", &v, &f, &apply) ) { vertProg = v; fragProg = f; if( LinkProgram() ) { bgl::blUseProgramObjectARB( mShader ); mUse = apply!=0; Py_Return; } vertProg = 0; fragProg = 0; mUse = 0; bgl::blUseProgramObjectARB( 0 ); PyErr_Format(PyExc_ValueError, "GLSL Error"); } return NULL; #else Py_Return; #endif } KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" ) { #ifdef GL_ARB_shader_objects bgl::blDeleteObjectARB(mShader); bgl::blDeleteObjectARB(mFrag); bgl::blDeleteObjectARB(mVert); mShader = 0; mFrag = 0; mVert = 0; vertProg = 0; fragProg = 0; mOk = 0; mUse = 0; bgl::blUseProgramObjectARB(0); #endif Py_Return; } KX_PYMETHODDEF_DOC( BL_Shader, isValid, "isValid()" ) { return PyInt_FromLong( ( mShader !=0 && mOk ) ); } KX_PYMETHODDEF_DOC( BL_Shader, getVertexProg ,"getVertexProg( )" ) { return PyString_FromString(vertProg?vertProg:""); } KX_PYMETHODDEF_DOC( BL_Shader, getFragmentProg ,"getFragmentProg( )" ) { return PyString_FromString(fragProg?fragProg:""); } KX_PYMETHODDEF_DOC( BL_Shader, validate, "validate()") { #ifdef GL_ARB_shader_objects if(mShader==0) { PyErr_Format(PyExc_TypeError, "invalid shader object"); return NULL; } int stat = 0; bgl::blValidateProgramARB(mShader); bgl::blGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB, &stat); return PyInt_FromLong(!PrintInfo(stat, mShader, "Validation")); #else Py_Return; #endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" ) { #ifdef GL_ARB_shader_objects char *uniform=""; int index=-1; if(PyArg_ParseTuple(args, "si", &uniform, &index)) { if(mShader==0) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader, uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { if(index <= MAXTEX) { mSampler[index].loc = loc; }else { spit("Invalid texture sample index: " << index); } Py_Return; } } return NULL; #else Py_Return; #endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )" ) { int pass = 1; if(!PyArg_ParseTuple(args, "i", &pass)) return NULL; mPass = 1; Py_Return; } /// access functions KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" ) { #ifdef GL_ARB_shader_objects char *uniform=""; float value=0; if(PyArg_ParseTuple(args, "sf", &uniform, &value )) { if( mShader==0 ) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader, uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { bgl::blUseProgramObjectARB( mShader ); bgl::blUniform1fARB( loc, value ); Py_Return; } } return NULL; #else Py_Return; #endif } KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)") { #ifdef GL_ARB_shader_objects char *uniform=""; float array[2]={ 0,0 }; if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] )) { if( mShader==0 ) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader , uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { bgl::blUseProgramObjectARB( mShader ); bgl::blUniform2fARB(loc, array[0],array[1] ); Py_Return; } } return NULL; #else Py_Return; #endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") { #ifdef GL_ARB_shader_objects char *uniform=""; float array[3]={0,0,0}; if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2])) { if(mShader==0) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader , uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { bgl::blUseProgramObjectARB(mShader); bgl::blUniform3fARB(loc, array[0],array[1],array[2]); Py_Return; } } return NULL; #else Py_Return; #endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ") { #ifdef GL_ARB_shader_objects char *uniform=""; float array[4]={0,0,0,0}; if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3])) { if(mShader==0) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader , uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { bgl::blUseProgramObjectARB(mShader); bgl::blUniform4fARB(loc, array[0],array[1],array[2], array[3]); Py_Return; } } return NULL; #else Py_Return; #endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" ) { #ifdef GL_ARB_shader_objects char *uniform=""; int value=0; if(PyArg_ParseTuple(args, "si", &uniform, &value )) { if( mShader==0 ) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader, uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { bgl::blUseProgramObjectARB( mShader ); bgl::blUniform1iARB( loc, value ); Py_Return; } } return NULL; #else Py_Return; #endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)") { #ifdef GL_ARB_shader_objects char *uniform=""; int array[2]={ 0,0 }; if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] )) { if( mShader==0 ) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader , uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { bgl::blUseProgramObjectARB( mShader ); bgl::blUniform2iARB(loc, array[0],array[1] ); Py_Return; } } return NULL; #else Py_Return; #endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") { #ifdef GL_ARB_shader_objects char *uniform=""; int array[3]={0,0,0}; if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2])) { if(mShader==0) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader , uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { bgl::blUseProgramObjectARB(mShader); bgl::blUniform3iARB(loc, array[0],array[1],array[2]); Py_Return; } } return NULL; #else Py_Return; #endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ") { #ifdef GL_ARB_shader_objects char *uniform=""; int array[4]={0,0,0, 0}; if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] )) { if(mShader==0) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader , uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { bgl::blUseProgramObjectARB(mShader); bgl::blUniform4iARB(loc, array[0],array[1],array[2], array[3]); Py_Return; } } return NULL; #else Py_Return; #endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )") { #ifdef GL_ARB_shader_objects char*uniform = ""; PyObject *listPtr =0; float array_data[4] = {0.f,0.f,0.f,0.f}; if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr)) { if(mShader==0) { PyErr_Format(PyExc_ValueError, "invalid shader object"); return NULL; } int loc= bgl::blGetUniformLocationARB(mShader , uniform); if( loc==-1 ) { spit("Invalid uniform value: " << uniform << "."); Py_Return; }else { if(PySequence_Check(listPtr)) { unsigned int list_size = PySequence_Size(listPtr); for(unsigned int i=0; (i