Changeset View
Changeset View
Standalone View
Standalone View
source/gameengine/Ketsji/BL_Shader.cpp
| Context not available. | |||||
| * \ingroup ketsji | * \ingroup ketsji | ||||
| */ | */ | ||||
| #include "glew-mx.h" | |||||
| #include <iostream> | |||||
| #include "BL_Shader.h" | #include "BL_Shader.h" | ||||
| #include "BL_Material.h" | #include "RAS_Texture.h" // for RAS_Texture::MaxUnits | ||||
| #include "RAS_MeshSlot.h" | |||||
| #include "RAS_MeshUser.h" | |||||
| #include "MT_assert.h" | |||||
| #include "MT_Matrix4x4.h" | |||||
| #include "MT_Matrix3x3.h" | |||||
| #include "KX_PyMath.h" | #include "KX_PyMath.h" | ||||
| #include "KX_PythonInit.h" | #include "KX_PythonInit.h" | ||||
| #include "MEM_guardedalloc.h" | #include "KX_GameObject.h" | ||||
| #include "RAS_MeshObject.h" | #ifdef WITH_PYTHON | ||||
| #include "RAS_IRasterizer.h" | # include "EXP_PythonCallBack.h" | ||||
| #endif // WITH_PYTHON | |||||
| #define spit(x) std::cout << x << std::endl; | |||||
| #define SORT_UNIFORMS 1 | |||||
| #define UNIFORM_MAX_LEN (int)sizeof(float) * 16 | |||||
| #define MAX_LOG_LEN 262144 // bounds | |||||
| BL_Uniform::BL_Uniform(int data_size) | |||||
| : | |||||
| mLoc(-1), | |||||
| mDirty(true), | |||||
| mType(UNI_NONE), | |||||
| mTranspose(0), | |||||
| mDataLen(data_size) | |||||
| { | |||||
| #ifdef SORT_UNIFORMS | |||||
| MT_assert((int)mDataLen <= UNIFORM_MAX_LEN); | |||||
| mData = (void *)MEM_mallocN(mDataLen, "shader-uniform-alloc"); | |||||
| #endif | |||||
| } | |||||
| BL_Uniform::~BL_Uniform() | |||||
| { | |||||
| #ifdef SORT_UNIFORMS | |||||
| if (mData) { | |||||
| MEM_freeN(mData); | |||||
| mData = NULL; | |||||
| } | |||||
| #endif | |||||
| } | |||||
| bool BL_Uniform::Apply(class BL_Shader *shader) | |||||
| { | |||||
| #ifdef SORT_UNIFORMS | |||||
| RAS_IRasterizer *ras; | |||||
| MT_assert(mType > UNI_NONE && mType < UNI_MAX && mData); | |||||
| if (!mDirty) | |||||
| return false; | |||||
| mDirty = false; | |||||
| switch (mType) { | |||||
| case UNI_FLOAT: | |||||
| { | |||||
| float *f = (float *)mData; | |||||
| glUniform1fARB(mLoc, (GLfloat)*f); | |||||
| break; | |||||
| } | |||||
| case UNI_FLOAT_EYE: | |||||
| { | |||||
| float *f = (float*)mData; | |||||
| ras = KX_GetActiveEngine()->GetRasterizer(); | |||||
| *f = (ras->GetEye() == RAS_IRasterizer::RAS_STEREO_LEFTEYE) ? 0.0f : 0.5f; | |||||
| glUniform1fARB(mLoc, (GLfloat)*f); | |||||
| mDirty = (ras->Stereo()) ? true : false; | |||||
| break; | |||||
| } | |||||
| case UNI_INT: | |||||
| { | |||||
| int *f = (int *)mData; | |||||
| glUniform1iARB(mLoc, (GLint)*f); | |||||
| break; | |||||
| } | |||||
| case UNI_FLOAT2: | |||||
| { | |||||
| float *f = (float *)mData; | |||||
| glUniform2fvARB(mLoc, 1, (GLfloat *)f); | |||||
| break; | |||||
| } | |||||
| case UNI_FLOAT3: | |||||
| { | |||||
| float *f = (float *)mData; | |||||
| glUniform3fvARB(mLoc, 1, (GLfloat *)f); | |||||
| break; | |||||
| } | |||||
| case UNI_FLOAT4: | |||||
| { | |||||
| float *f = (float *)mData; | |||||
| glUniform4fvARB(mLoc, 1, (GLfloat *)f); | |||||
| break; | |||||
| } | |||||
| case UNI_INT2: | |||||
| { | |||||
| int *f = (int *)mData; | |||||
| glUniform2ivARB(mLoc, 1, (GLint *)f); | |||||
| break; | |||||
| } | |||||
| case UNI_INT3: | |||||
| { | |||||
| int *f = (int *)mData; | |||||
| glUniform3ivARB(mLoc, 1, (GLint *)f); | |||||
| break; | |||||
| } | |||||
| case UNI_INT4: | |||||
| { | |||||
| int *f = (int *)mData; | |||||
| glUniform4ivARB(mLoc, 1, (GLint *)f); | |||||
| break; | |||||
| } | |||||
| case UNI_MAT4: | |||||
| { | |||||
| float *f = (float *)mData; | |||||
| glUniformMatrix4fvARB(mLoc, 1, mTranspose ? GL_TRUE : GL_FALSE, (GLfloat *)f); | |||||
| break; | |||||
| } | |||||
| case UNI_MAT3: | |||||
| { | |||||
| float *f = (float *)mData; | |||||
| glUniformMatrix3fvARB(mLoc, 1, mTranspose ? GL_TRUE : GL_FALSE, (GLfloat *)f); | |||||
| break; | |||||
| } | |||||
| } | |||||
| return mDirty; | |||||
| #endif | |||||
| } | |||||
| void BL_Uniform::SetData(int location, int type, bool transpose) | #include "CM_Message.h" | ||||
| { | |||||
| #ifdef SORT_UNIFORMS | |||||
| mType = type; | |||||
| mLoc = location; | |||||
| mDirty = true; | |||||
| #endif | |||||
| } | |||||
| bool BL_Shader::Ok()const | |||||
| { | |||||
| return (mShader != 0 && mOk && mUse); | |||||
| } | |||||
| BL_Shader::BL_Shader() | BL_Shader::BL_Shader() | ||||
| : | |||||
| PyObjectPlus(), | |||||
| mShader(0), | |||||
| mPass(1), | |||||
| mOk(0), | |||||
| mUse(0), | |||||
| mAttr(0), | |||||
| vertProg(NULL), | |||||
| fragProg(NULL), | |||||
| mError(0), | |||||
| mDirty(true) | |||||
| { | |||||
| // if !GLEW_ARB_shader_objects this class will not be used | |||||
| //for (int i=0; i<MAXTEX; i++) { | |||||
| // mSampler[i] = BL_Sampler(); | |||||
| //} | |||||
| } | |||||
| BL_Shader::~BL_Shader() | |||||
| { | |||||
| //for (int i=0; i<MAXTEX; i++) { | |||||
| // if (mSampler[i].mOwn) { | |||||
| // if (mSampler[i].mTexture) | |||||
| // mSampler[i].mTexture->DeleteTex(); | |||||
| // } | |||||
| //} | |||||
| ClearUniforms(); | |||||
| if (mShader) { | |||||
| glDeleteObjectARB(mShader); | |||||
| mShader = 0; | |||||
| } | |||||
| vertProg = NULL; | |||||
| fragProg = NULL; | |||||
| mOk = 0; | |||||
| glUseProgramObjectARB(0); | |||||
| } | |||||
| void BL_Shader::ClearUniforms() | |||||
| { | |||||
| BL_UniformVec::iterator it = mUniforms.begin(); | |||||
| while (it != mUniforms.end()) { | |||||
| delete *it; | |||||
| it++; | |||||
| } | |||||
| mUniforms.clear(); | |||||
| BL_UniformVecDef::iterator itp = mPreDef.begin(); | |||||
| while (itp != mPreDef.end()) { | |||||
| delete *itp; | |||||
| itp++; | |||||
| } | |||||
| mPreDef.clear(); | |||||
| } | |||||
| BL_Uniform *BL_Shader::FindUniform(const int location) | |||||
| { | |||||
| #ifdef SORT_UNIFORMS | |||||
| BL_UniformVec::iterator it = mUniforms.begin(); | |||||
| while (it != mUniforms.end()) { | |||||
| if ((*it)->GetLocation() == location) { | |||||
| return *it; | |||||
| } | |||||
| it++; | |||||
| } | |||||
| #endif | |||||
| return NULL; | |||||
| } | |||||
| void BL_Shader::SetUniformfv(int location, int type, float *param, int size, bool transpose) | |||||
| { | |||||
| #ifdef SORT_UNIFORMS | |||||
| BL_Uniform *uni = FindUniform(location); | |||||
| if (uni) { | |||||
| memcpy(uni->getData(), param, size); | |||||
| uni->SetData(location, type, transpose); | |||||
| } | |||||
| else { | |||||
| uni = new BL_Uniform(size); | |||||
| memcpy(uni->getData(), param, size); | |||||
| uni->SetData(location, type, transpose); | |||||
| mUniforms.push_back(uni); | |||||
| } | |||||
| mDirty = true; | |||||
| #endif | |||||
| } | |||||
| void BL_Shader::SetUniformiv(int location, int type, int *param, int size, bool transpose) | |||||
| { | |||||
| #ifdef SORT_UNIFORMS | |||||
| BL_Uniform *uni = FindUniform(location); | |||||
| if (uni) { | |||||
| memcpy(uni->getData(), param, size); | |||||
| uni->SetData(location, type, transpose); | |||||
| } | |||||
| else { | |||||
| uni = new BL_Uniform(size); | |||||
| memcpy(uni->getData(), param, size); | |||||
| uni->SetData(location, type, transpose); | |||||
| mUniforms.push_back(uni); | |||||
| } | |||||
| mDirty = true; | |||||
| #endif | |||||
| } | |||||
| void BL_Shader::ApplyShader() | |||||
| { | { | ||||
| #ifdef SORT_UNIFORMS | #ifdef WITH_PYTHON | ||||
| if (!mDirty) { | for (unsigned short i = 0; i < CALLBACKS_MAX; ++i) { | ||||
| return; | m_callbacks[i] = PyList_New(0); | ||||
| } | |||||
| mDirty = false; | |||||
| for (unsigned int i=0; i<mUniforms.size(); i++) { | |||||
| mDirty |= mUniforms[i]->Apply(this); | |||||
| } | } | ||||
| #endif | #endif // WITH_PYTHON | ||||
| } | |||||
| void BL_Shader::UnloadShader() | |||||
| { | |||||
| // | |||||
| } | } | ||||
| bool BL_Shader::LinkProgram() | BL_Shader::~BL_Shader() | ||||
| { | { | ||||
| int vertlen = 0, fraglen = 0, proglen = 0; | #ifdef WITH_PYTHON | ||||
| int vertstatus = 0, fragstatus = 0, progstatus = 0; | for (unsigned short i = 0; i < CALLBACKS_MAX; ++i) { | ||||
| unsigned int tmpVert = 0, tmpFrag = 0, tmpProg = 0; | Py_XDECREF(m_callbacks[i]); | ||||
| int char_len = 0; | |||||
| char *logInf = NULL; | |||||
| if (mError) { | |||||
| goto programError; | |||||
| } | |||||
| if (!vertProg || !fragProg) { | |||||
| spit("Invalid GLSL sources"); | |||||
| return false; | |||||
| } | |||||
| if (!GLEW_ARB_fragment_shader) { | |||||
| spit("Fragment shaders not supported"); | |||||
| return false; | |||||
| } | |||||
| if (!GLEW_ARB_vertex_shader) { | |||||
| spit("Vertex shaders not supported"); | |||||
| return false; | |||||
| } | |||||
| if (vertProg[0] != 0) { | |||||
| // -- vertex shader ------------------ | |||||
| tmpVert = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); | |||||
| glShaderSourceARB(tmpVert, 1, (const char**)&vertProg, 0); | |||||
| glCompileShaderARB(tmpVert); | |||||
| glGetObjectParameterivARB(tmpVert, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*)&vertlen); | |||||
| // print info if any | |||||
| if (vertlen > 0 && vertlen < MAX_LOG_LEN) { | |||||
| logInf = (char*)MEM_mallocN(vertlen, "vert-log"); | |||||
| glGetInfoLogARB(tmpVert, vertlen, (GLsizei*)&char_len, logInf); | |||||
| if (char_len > 0) { | |||||
| spit("---- Vertex Shader Error ----"); | |||||
| spit(logInf); | |||||
| } | |||||
| MEM_freeN(logInf); | |||||
| logInf = 0; | |||||
| } | |||||
| // check for compile errors | |||||
| glGetObjectParameterivARB(tmpVert, GL_OBJECT_COMPILE_STATUS_ARB, (GLint*)&vertstatus); | |||||
| if (!vertstatus) { | |||||
| spit("---- Vertex shader failed to compile ----"); | |||||
| goto programError; | |||||
| } | |||||
| } | |||||
| if (fragProg[0] != 0) { | |||||
| // -- fragment shader ---------------- | |||||
| tmpFrag = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); | |||||
| glShaderSourceARB(tmpFrag, 1, (const char**)&fragProg, 0); | |||||
| glCompileShaderARB(tmpFrag); | |||||
| glGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*)&fraglen); | |||||
| if (fraglen > 0 && fraglen < MAX_LOG_LEN) { | |||||
| logInf = (char*)MEM_mallocN(fraglen, "frag-log"); | |||||
| glGetInfoLogARB(tmpFrag, fraglen, (GLsizei*)&char_len, logInf); | |||||
| if (char_len > 0) { | |||||
| spit("---- Fragment Shader Error ----"); | |||||
| spit(logInf); | |||||
| } | |||||
| MEM_freeN(logInf); | |||||
| logInf = 0; | |||||
| } | |||||
| glGetObjectParameterivARB(tmpFrag, GL_OBJECT_COMPILE_STATUS_ARB, (GLint*)&fragstatus); | |||||
| if (!fragstatus) { | |||||
| spit("---- Fragment shader failed to compile ----"); | |||||
| goto programError; | |||||
| } | |||||
| } | |||||
| if (!tmpFrag && !tmpVert) { | |||||
| spit("---- No shader given ----"); | |||||
| goto programError; | |||||
| } | |||||
| // -- program ------------------------ | |||||
| // set compiled vert/frag shader & link | |||||
| tmpProg = glCreateProgramObjectARB(); | |||||
| if (tmpVert) { | |||||
| glAttachObjectARB(tmpProg, tmpVert); | |||||
| } | |||||
| if (tmpFrag) { | |||||
| glAttachObjectARB(tmpProg, tmpFrag); | |||||
| } | |||||
| glLinkProgramARB(tmpProg); | |||||
| glGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint *)&proglen); | |||||
| glGetObjectParameterivARB(tmpProg, GL_OBJECT_LINK_STATUS_ARB, (GLint *)&progstatus); | |||||
| if (proglen > 0 && proglen < MAX_LOG_LEN) { | |||||
| logInf = (char *)MEM_mallocN(proglen, "prog-log"); | |||||
| glGetInfoLogARB(tmpProg, proglen, (GLsizei *)&char_len, logInf); | |||||
| if (char_len > 0) { | |||||
| spit("---- GLSL Program ----"); | |||||
| spit(logInf); | |||||
| } | |||||
| MEM_freeN(logInf); | |||||
| logInf = 0; | |||||
| } | |||||
| if (!progstatus) { | |||||
| spit("---- GLSL program failed to link ----"); | |||||
| goto programError; | |||||
| } | |||||
| // set | |||||
| mShader = tmpProg; | |||||
| if (tmpVert) { | |||||
| glDeleteObjectARB(tmpVert); | |||||
| } | |||||
| if (tmpFrag) { | |||||
| glDeleteObjectARB(tmpFrag); | |||||
| } | |||||
| mOk = 1; | |||||
| mError = 0; | |||||
| return true; | |||||
| programError: | |||||
| if (tmpVert) { | |||||
| glDeleteObjectARB(tmpVert); | |||||
| tmpVert = 0; | |||||
| } | |||||
| if (tmpFrag) { | |||||
| glDeleteObjectARB(tmpFrag); | |||||
| tmpFrag = 0; | |||||
| } | |||||
| if (tmpProg) { | |||||
| glDeleteObjectARB(tmpProg); | |||||
| tmpProg = 0; | |||||
| } | } | ||||
| #endif // WITH_PYTHON | |||||
| mOk = 0; | |||||
| mUse = 0; | |||||
| mError = 1; | |||||
| return false; | |||||
| } | |||||
| const char *BL_Shader::GetVertPtr() | |||||
| { | |||||
| return vertProg ? vertProg : NULL; | |||||
| } | } | ||||
| const char *BL_Shader::GetFragPtr() | #ifdef WITH_PYTHON | ||||
| { | |||||
| return fragProg ? fragProg : NULL; | |||||
| } | |||||
| void BL_Shader::SetVertPtr(char *vert) | |||||
| { | |||||
| vertProg = vert; | |||||
| } | |||||
| void BL_Shader::SetFragPtr(char *frag) | |||||
| { | |||||
| fragProg = frag; | |||||
| } | |||||
| unsigned int BL_Shader::GetProg() | PyObject *BL_Shader::GetCallbacks(BL_Shader::CallbacksType type) | ||||
| { | { | ||||
| return mShader; | return m_callbacks[type]; | ||||
| } | } | ||||
| //const BL_Sampler *BL_Shader::GetSampler(int i) | void BL_Shader::SetCallbacks(BL_Shader::CallbacksType type, PyObject *callbacks) | ||||
| //{ | |||||
| // MT_assert(i<=MAXTEX); | |||||
| // return &mSampler[i]; | |||||
| //} | |||||
| void BL_Shader::SetSampler(int loc, int unit) | |||||
| { | { | ||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | Py_XDECREF(m_callbacks[type]); | ||||
| glUniform1iARB(loc, unit); | Py_INCREF(callbacks); | ||||
| } | m_callbacks[type] = callbacks; | ||||
| } | } | ||||
| //void BL_Shader::InitializeSampler(int unit, BL_Texture *texture) | #endif // WITH_PYTHON | ||||
| //{ | |||||
| // MT_assert(unit <= MAXTEX); | |||||
| // mSampler[unit].mTexture = texture; | |||||
| // mSampler[unit].mLoc = -1; | |||||
| // mSampler[unit].mOwn = 0; | |||||
| //} | |||||
| void BL_Shader::SetProg(bool enable) | void BL_Shader::SetProg(bool enable) | ||||
| { | { | ||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | #ifdef WITH_PYTHON | ||||
| if (mShader != 0 && mOk && enable) { | if (enable && PyList_GET_SIZE(m_callbacks[CALLBACKS_BIND]) > 0) { | ||||
| glUseProgramObjectARB(mShader); | RunPythonCallBackList(m_callbacks[CALLBACKS_BIND], NULL, 0, 0); | ||||
| } | |||||
| else { | |||||
| glUseProgramObjectARB(0); | |||||
| } | |||||
| } | |||||
| } | |||||
| void BL_Shader::Update(const RAS_MeshSlot &ms, RAS_IRasterizer *rasty) | |||||
| { | |||||
| if (!Ok() || !mPreDef.size()) { | |||||
| return; | |||||
| } | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| MT_Matrix4x4 model; | |||||
| model.setValue(ms.m_OpenGLMatrix); | |||||
| const MT_Matrix4x4 &view = rasty->GetViewMatrix(); | |||||
| if (mAttr == SHD_TANGENT) { | |||||
| ms.m_mesh->SetMeshModified(true); | |||||
| } | |||||
| BL_UniformVecDef::iterator it; | |||||
| for (it = mPreDef.begin(); it != mPreDef.end(); it++) { | |||||
| BL_DefUniform *uni = (*it); | |||||
| if (uni->mLoc == -1) { | |||||
| continue; | |||||
| } | |||||
| switch (uni->mType) { | |||||
| case MODELMATRIX: | |||||
| { | |||||
| SetUniform(uni->mLoc, model); | |||||
| break; | |||||
| } | |||||
| case MODELMATRIX_TRANSPOSE: | |||||
| { | |||||
| SetUniform(uni->mLoc, model, true); | |||||
| break; | |||||
| } | |||||
| case MODELMATRIX_INVERSE: | |||||
| { | |||||
| model.invert(); | |||||
| SetUniform(uni->mLoc, model); | |||||
| break; | |||||
| } | |||||
| case MODELMATRIX_INVERSETRANSPOSE: | |||||
| { | |||||
| model.invert(); | |||||
| SetUniform(uni->mLoc, model, true); | |||||
| break; | |||||
| } | |||||
| case MODELVIEWMATRIX: | |||||
| { | |||||
| SetUniform(uni->mLoc, view * model); | |||||
| break; | |||||
| } | |||||
| case MODELVIEWMATRIX_TRANSPOSE: | |||||
| { | |||||
| MT_Matrix4x4 mat(view * model); | |||||
| SetUniform(uni->mLoc, mat, true); | |||||
| break; | |||||
| } | |||||
| case MODELVIEWMATRIX_INVERSE: | |||||
| { | |||||
| MT_Matrix4x4 mat(view * model); | |||||
| mat.invert(); | |||||
| SetUniform(uni->mLoc, mat); | |||||
| break; | |||||
| } | |||||
| case MODELVIEWMATRIX_INVERSETRANSPOSE: | |||||
| { | |||||
| MT_Matrix4x4 mat(view * model); | |||||
| mat.invert(); | |||||
| SetUniform(uni->mLoc, mat, true); | |||||
| break; | |||||
| } | |||||
| case CAM_POS: | |||||
| { | |||||
| MT_Point3 pos(rasty->GetCameraPosition()); | |||||
| SetUniform(uni->mLoc, pos); | |||||
| break; | |||||
| } | |||||
| case VIEWMATRIX: | |||||
| { | |||||
| SetUniform(uni->mLoc, view); | |||||
| break; | |||||
| } | |||||
| case VIEWMATRIX_TRANSPOSE: | |||||
| { | |||||
| SetUniform(uni->mLoc, view, true); | |||||
| break; | |||||
| } | |||||
| case VIEWMATRIX_INVERSE: | |||||
| { | |||||
| MT_Matrix4x4 viewinv = view; | |||||
| viewinv.invert(); | |||||
| SetUniform(uni->mLoc, view); | |||||
| break; | |||||
| } | |||||
| case VIEWMATRIX_INVERSETRANSPOSE: | |||||
| { | |||||
| MT_Matrix4x4 viewinv = view; | |||||
| viewinv.invert(); | |||||
| SetUniform(uni->mLoc, view, true); | |||||
| break; | |||||
| } | |||||
| case CONSTANT_TIMER: | |||||
| { | |||||
| SetUniform(uni->mLoc, (float)rasty->GetTime()); | |||||
| break; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| int BL_Shader::GetAttribLocation(const char *name) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| return glGetAttribLocationARB(mShader, name); | |||||
| } | |||||
| return -1; | |||||
| } | |||||
| void BL_Shader::BindAttribute(const char *attr, int loc) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| glBindAttribLocationARB(mShader, loc, attr); | |||||
| } | |||||
| } | |||||
| int BL_Shader::GetUniformLocation(const char *name) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| MT_assert(mShader != 0); | |||||
| int location = glGetUniformLocationARB(mShader, name); | |||||
| if (location == -1) { | |||||
| spit("Invalid uniform value: " << name << "."); | |||||
| } | |||||
| return location; | |||||
| } | |||||
| return -1; | |||||
| } | |||||
| void BL_Shader::SetUniform(int uniform, const MT_Tuple2 &vec) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| float value[2]; | |||||
| vec.getValue(value); | |||||
| glUniform2fvARB(uniform, 1, value); | |||||
| } | |||||
| } | |||||
| void BL_Shader::SetUniform(int uniform, const MT_Tuple3 &vec) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| float value[3]; | |||||
| vec.getValue(value); | |||||
| glUniform3fvARB(uniform, 1, value); | |||||
| } | |||||
| } | |||||
| void BL_Shader::SetUniform(int uniform, const MT_Tuple4 &vec) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| float value[4]; | |||||
| vec.getValue(value); | |||||
| glUniform4fvARB(uniform, 1, value); | |||||
| } | |||||
| } | |||||
| void BL_Shader::SetUniform(int uniform, const unsigned int &val) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| glUniform1iARB(uniform, val); | |||||
| } | |||||
| } | |||||
| void BL_Shader::SetUniform(int uniform, const int val) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| glUniform1iARB(uniform, val); | |||||
| } | |||||
| } | |||||
| void BL_Shader::SetUniform(int uniform, const float &val) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| glUniform1fARB(uniform, val); | |||||
| } | } | ||||
| } | #endif // WITH_PYTHON | ||||
| void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4 &vec, bool transpose) | RAS_Shader::SetProg(enable); | ||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| float value[16]; | |||||
| // note: getValue gives back column major as needed by OpenGL | |||||
| vec.getValue(value); | |||||
| glUniformMatrix4fvARB(uniform, 1, transpose ? GL_TRUE : GL_FALSE, value); | |||||
| } | |||||
| } | } | ||||
| void BL_Shader::SetUniform(int uniform, const MT_Matrix3x3 &vec, bool transpose) | void BL_Shader::Update(RAS_IRasterizer *rasty, RAS_MeshSlot *ms) | ||||
| { | { | ||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | #ifdef WITH_PYTHON | ||||
| float value[9]; | if (PyList_GET_SIZE(m_callbacks[CALLBACKS_OBJECT]) > 0) { | ||||
| value[0] = (float)vec[0][0]; | KX_GameObject *gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo *)ms->m_meshUser->GetClientObject()); | ||||
| value[1] = (float)vec[1][0]; | PyObject *args[] = {gameobj->GetProxy()}; | ||||
| value[2] = (float)vec[2][0]; | RunPythonCallBackList(m_callbacks[CALLBACKS_OBJECT], args, 0, ARRAY_SIZE(args)); | ||||
| value[3] = (float)vec[0][1]; | |||||
| value[4] = (float)vec[1][1]; | |||||
| value[5] = (float)vec[2][1]; | |||||
| value[6] = (float)vec[0][2]; | |||||
| value[7] = (float)vec[1][2]; | |||||
| value[8] = (float)vec[2][2]; | |||||
| glUniformMatrix3fvARB(uniform, 1, transpose ? GL_TRUE : GL_FALSE, value); | |||||
| } | |||||
| } | |||||
| void BL_Shader::SetUniform(int uniform, const float *val, int len) | |||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| if (len == 2) { | |||||
| glUniform2fvARB(uniform, 1, (GLfloat *)val); | |||||
| } | |||||
| else if (len == 3) { | |||||
| glUniform3fvARB(uniform, 1, (GLfloat *)val); | |||||
| } | |||||
| else if (len == 4) { | |||||
| glUniform4fvARB(uniform, 1, (GLfloat *)val); | |||||
| } | |||||
| else { | |||||
| MT_assert(0); | |||||
| } | |||||
| } | } | ||||
| } | #endif // WITH_PYTHON | ||||
| void BL_Shader::SetUniform(int uniform, const int *val, int len) | RAS_Shader::Update(rasty, MT_Matrix4x4(ms->m_meshUser->GetMatrix())); | ||||
| { | |||||
| if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) { | |||||
| if (len == 2) { | |||||
| glUniform2ivARB(uniform, 1, (GLint *)val); | |||||
| } | |||||
| else if (len == 3) { | |||||
| glUniform3ivARB(uniform, 1, (GLint *)val); | |||||
| } | |||||
| else if (len == 4) { | |||||
| glUniform4ivARB(uniform, 1, (GLint *)val); | |||||
| } | |||||
| else { | |||||
| MT_assert(0); | |||||
| } | |||||
| } | |||||
| } | } | ||||
| #ifdef WITH_PYTHON | #ifdef WITH_PYTHON | ||||
| PyMethodDef BL_Shader::Methods[] = { | PyMethodDef BL_Shader::Methods[] = { | ||||
| // creation | // creation | ||||
| KX_PYMETHODTABLE(BL_Shader, setSource), | KX_PYMETHODTABLE(BL_Shader, setSource), | ||||
| KX_PYMETHODTABLE(BL_Shader, setSourceList), | |||||
| KX_PYMETHODTABLE(BL_Shader, delSource), | KX_PYMETHODTABLE(BL_Shader, delSource), | ||||
| KX_PYMETHODTABLE(BL_Shader, getVertexProg), | KX_PYMETHODTABLE(BL_Shader, getVertexProg), | ||||
| KX_PYMETHODTABLE(BL_Shader, getFragmentProg), | KX_PYMETHODTABLE(BL_Shader, getFragmentProg), | ||||
| KX_PYMETHODTABLE(BL_Shader, setNumberOfPasses), | |||||
| KX_PYMETHODTABLE(BL_Shader, validate), | KX_PYMETHODTABLE(BL_Shader, validate), | ||||
| // access functions | // access functions | ||||
| KX_PYMETHODTABLE(BL_Shader, isValid), | KX_PYMETHODTABLE(BL_Shader, isValid), | ||||
| Context not available. | |||||
| }; | }; | ||||
| PyAttributeDef BL_Shader::Attributes[] = { | PyAttributeDef BL_Shader::Attributes[] = { | ||||
| {NULL} //Sentinel | KX_PYATTRIBUTE_RW_FUNCTION("enabled", BL_Shader, pyattr_get_enabled, pyattr_set_enabled), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("bindCallbacks", BL_Shader, pyattr_get_callbacks, pyattr_set_callbacks), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("objectCallbacks", BL_Shader, pyattr_get_callbacks, pyattr_set_callbacks), | |||||
| KX_PYATTRIBUTE_NULL //Sentinel | |||||
| }; | }; | ||||
| PyTypeObject BL_Shader::Type = { | PyTypeObject BL_Shader::Type = { | ||||
| Context not available. | |||||
| py_base_new | py_base_new | ||||
| }; | }; | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, setSource, " setSource(vertexProgram, fragmentProgram)") | PyObject *BL_Shader::pyattr_get_enabled(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | |||||
| BL_Shader* self = static_cast<BL_Shader*>(self_v); | |||||
| return PyBool_FromLong(self->GetEnabled()); | |||||
| } | |||||
| int BL_Shader::pyattr_set_enabled(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | { | ||||
| if (mShader != 0 && mOk) { | BL_Shader* self = static_cast<BL_Shader*>(self_v); | ||||
| int param = PyObject_IsTrue(value); | |||||
| if (param == -1) { | |||||
| PyErr_SetString(PyExc_AttributeError, "shader.enabled = bool: BL_Shader, expected True or False"); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| self->SetEnabled(param); | |||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | |||||
| static std::map<const std::string, BL_Shader::CallbacksType> callbacksTable = { | |||||
| {"bindCallbacks", BL_Shader::CALLBACKS_BIND}, | |||||
| {"objectCallbacks", BL_Shader::CALLBACKS_OBJECT} | |||||
| }; | |||||
| PyObject *BL_Shader::pyattr_get_callbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| BL_Shader *self = static_cast<BL_Shader *>(self_v); | |||||
| PyObject *callbacks = self->GetCallbacks(callbacksTable[attrdef->m_name]); | |||||
| Py_INCREF(callbacks); | |||||
| return callbacks; | |||||
| } | |||||
| int BL_Shader::pyattr_set_callbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | |||||
| BL_Shader *self = static_cast<BL_Shader *>(self_v); | |||||
| if (!PyList_CheckExact(value)) { | |||||
| PyErr_Format(PyExc_AttributeError, "shader.%s = bool: BL_Shader, expected a list", attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| self->SetCallbacks(callbacksTable[attrdef->m_name], value); | |||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setSource, " setSource(vertexProgram, fragmentProgram, apply)") | |||||
| { | |||||
| if (m_shader) { | |||||
| // already set... | // already set... | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| int apply = 0; | int apply = 0; | ||||
| if (PyArg_ParseTuple(args, "ssi:setSource", &v, &f, &apply)) { | if (PyArg_ParseTuple(args, "ssi:setSource", &v, &f, &apply)) { | ||||
| vertProg = v; | m_progs[VERTEX_PROGRAM] = std::string(v); | ||||
| fragProg = f; | m_progs[FRAGMENT_PROGRAM] = std::string(f); | ||||
| m_progs[GEOMETRY_PROGRAM] = ""; | |||||
| if (LinkProgram()) { | if (LinkProgram()) { | ||||
| glUseProgramObjectARB(mShader); | SetProg(true); | ||||
| mUse = apply != 0; | m_use = apply != 0; | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| vertProg = NULL; | m_progs[VERTEX_PROGRAM] = ""; | ||||
| fragProg = NULL; | m_progs[FRAGMENT_PROGRAM] = ""; | ||||
| mUse = 0; | m_use = 0; | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, setSourceList, " setSourceList(sources, apply)") | |||||
| { | |||||
| if (m_shader) { | |||||
| // already set... | |||||
| Py_RETURN_NONE; | |||||
| } | |||||
| PyObject *pydict; | |||||
| int apply = 0; | |||||
| if (!PyArg_ParseTuple(args, "O!i:setSourceList", &PyDict_Type, &pydict, &apply)) { | |||||
| return NULL; | |||||
| } | |||||
| bool error = false; | |||||
| static const char *progname[MAX_PROGRAM] = {"vertex", "fragment", "geometry"}; | |||||
| static const bool optional[MAX_PROGRAM] = {false, false, true}; | |||||
| for (unsigned short i = 0; i < MAX_PROGRAM; ++i) { | |||||
| PyObject *pyprog = PyDict_GetItemString(pydict, progname[i]); | |||||
| if (!optional[i]) { | |||||
| if (!pyprog) { | |||||
| error = true; | |||||
| PyErr_Format(PyExc_SystemError, "setSourceList(sources, apply): BL_Shader, non optional %s program missing", progname[i]); | |||||
| break; | |||||
| } | |||||
| else if (!PyUnicode_Check(pyprog)) { | |||||
| error = true; | |||||
| PyErr_Format(PyExc_SystemError, "setSourceList(sources, apply): BL_Shader, non optional %s program is not a string", progname[i]); | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (pyprog) { | |||||
| m_progs[i] = std::string(_PyUnicode_AsString(pyprog)); | |||||
| } | |||||
| } | |||||
| if (error) { | |||||
| for (unsigned short i = 0; i < MAX_PROGRAM; ++i) { | |||||
| m_progs[i] = ""; | |||||
| } | |||||
| m_use = 0; | |||||
| return NULL; | |||||
| } | |||||
| if (LinkProgram()) { | |||||
| SetProg(true); | |||||
| m_use = apply != 0; | |||||
| } | |||||
| Py_RETURN_NONE; | |||||
| } | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, delSource, "delSource( )") | KX_PYMETHODDEF_DOC(BL_Shader, delSource, "delSource( )") | ||||
| { | { | ||||
| ClearUniforms(); | ClearUniforms(); | ||||
| glUseProgramObjectARB(0); | DeleteShader(); | ||||
| glDeleteObjectARB(mShader); | |||||
| mShader = 0; | |||||
| mOk = 0; | |||||
| mUse = 0; | |||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, isValid, "isValid()") | KX_PYMETHODDEF_DOC(BL_Shader, isValid, "isValid()") | ||||
| { | { | ||||
| return PyBool_FromLong((mShader != 0 && mOk)); | return PyBool_FromLong(m_shader != NULL); | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, getVertexProg, "getVertexProg( )") | KX_PYMETHODDEF_DOC(BL_Shader, getVertexProg, "getVertexProg( )") | ||||
| { | { | ||||
| return PyUnicode_FromString(vertProg ? vertProg : ""); | return PyUnicode_FromStdString(m_progs[VERTEX_PROGRAM]); | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, getFragmentProg, "getFragmentProg( )") | KX_PYMETHODDEF_DOC(BL_Shader, getFragmentProg, "getFragmentProg( )") | ||||
| { | { | ||||
| return PyUnicode_FromString(fragProg ? fragProg : ""); | return PyUnicode_FromStdString(m_progs[FRAGMENT_PROGRAM]); | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, validate, "validate()") | KX_PYMETHODDEF_DOC(BL_Shader, validate, "validate()") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| if (mShader == 0) { | if (!m_shader) { | ||||
| PyErr_SetString(PyExc_TypeError, "shader.validate(): BL_Shader, invalid shader object"); | PyErr_SetString(PyExc_TypeError, "shader.validate(): BL_Shader, invalid shader object"); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| int stat = 0; | ValidateProgram(); | ||||
| glValidateProgramARB(mShader); | |||||
| glGetObjectParameterivARB(mShader, GL_OBJECT_VALIDATE_STATUS_ARB, (GLint *)&stat); | |||||
| if (stat > 0 && stat < MAX_LOG_LEN) { | |||||
| int char_len = 0; | |||||
| char *logInf = (char *)MEM_mallocN(stat, "validate-log"); | |||||
| glGetInfoLogARB(mShader, stat, (GLsizei *)&char_len, logInf); | |||||
| if (char_len > 0) { | |||||
| spit("---- GLSL Validation ----"); | |||||
| spit(logInf); | |||||
| } | |||||
| MEM_freeN(logInf); | |||||
| logInf = NULL; | |||||
| } | |||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, setSampler, "setSampler(name, index)") | KX_PYMETHODDEF_DOC(BL_Shader, setSampler, "setSampler(name, index)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| int loc = GetUniformLocation(uniform); | int loc = GetUniformLocation(uniform); | ||||
| if (loc != -1) { | if (loc != -1) { | ||||
| if (index >= MAXTEX || index < 0) { | if (index >= RAS_Texture::MaxUnits || index < 0) { | ||||
| spit("Invalid texture sample index: " << index); | CM_Warning("invalid texture sample index: " << index); | ||||
| } | } | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformiv(loc, BL_Uniform::UNI_INT, &index, (sizeof(int))); | SetUniformiv(loc, RAS_Uniform::UNI_INT, &index, (sizeof(int)), 1); | ||||
| #else | #else | ||||
| SetUniform(loc, index); | SetUniform(loc, index); | ||||
| #endif | #endif | ||||
| //if (index <= MAXTEX) | |||||
| // mSampler[index].mLoc = loc; | |||||
| //else | |||||
| // spit("Invalid texture sample index: " << index); | |||||
| } | } | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, setNumberOfPasses, "setNumberOfPasses( max-pass )") | |||||
| { | |||||
| int pass = 1; | |||||
| if (!PyArg_ParseTuple(args, "i:setNumberOfPasses", &pass)) { | |||||
| return NULL; | |||||
| } | |||||
| mPass = 1; | |||||
| Py_RETURN_NONE; | |||||
| } | |||||
| /// access functions | /// access functions | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniform1f, "setUniform1f(name, fx)") | KX_PYMETHODDEF_DOC(BL_Shader, setUniform1f, "setUniform1f(name, fx)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| if (loc != -1) { | if (loc != -1) { | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformfv(loc, BL_Uniform::UNI_FLOAT, &value, sizeof(float)); | SetUniformfv(loc, RAS_Uniform::UNI_FLOAT, &value, sizeof(float), 1); | ||||
| #else | #else | ||||
| SetUniform(loc, (float)value); | SetUniform(loc, (float)value); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniform2f, "setUniform2f(name, fx, fy)") | KX_PYMETHODDEF_DOC(BL_Shader, setUniform2f, "setUniform2f(name, fx, fy)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| if (loc != -1) { | if (loc != -1) { | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array, (sizeof(float) * 2)); | SetUniformfv(loc, RAS_Uniform::UNI_FLOAT2, array, (sizeof(float) * 2), 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array, 2); | SetUniform(loc, array, 2); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") | KX_PYMETHODDEF_DOC(BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| if (loc != -1) { | if (loc != -1) { | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array, (sizeof(float) * 3)); | SetUniformfv(loc, RAS_Uniform::UNI_FLOAT3, array, (sizeof(float) * 3), 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array, 3); | SetUniform(loc, array, 3); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ") | KX_PYMETHODDEF_DOC(BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| if (loc != -1) { | if (loc != -1) { | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array, (sizeof(float) * 4)); | SetUniformfv(loc, RAS_Uniform::UNI_FLOAT4, array, (sizeof(float) * 4), 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array, 4); | SetUniform(loc, array, 4); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniformEyef, "setUniformEyef(name)") | KX_PYMETHODDEF_DOC(BL_Shader, setUniformEyef, "setUniformEyef(name)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| const char *uniform; | const char *uniform; | ||||
| float value = 0.0f; | |||||
| if (PyArg_ParseTuple(args, "s:setUniformEyef", &uniform)) { | if (PyArg_ParseTuple(args, "s:setUniformEyef", &uniform)) { | ||||
| int loc = GetUniformLocation(uniform); | int loc = GetUniformLocation(uniform); | ||||
| if (loc != -1) { | if (loc != -1) { | ||||
| #ifdef SORT_UNIFORMS | bool defined = false; | ||||
| SetUniformfv(loc, BL_Uniform::UNI_FLOAT_EYE, &value, sizeof(float)); | RAS_UniformVecDef::iterator it = m_preDef.begin(); | ||||
| #else | while (it != m_preDef.end()) { | ||||
| SetUniform(loc, (int)value); | if ((*it)->m_loc == loc) { | ||||
| #endif | defined = true; | ||||
| break; | |||||
| } | |||||
| it++; | |||||
| } | |||||
| if (defined) { | |||||
| Py_RETURN_NONE; | |||||
| } | |||||
| RAS_DefUniform *uni = new RAS_DefUniform(); | |||||
| uni->m_loc = loc; | |||||
| uni->m_type = EYE; | |||||
| uni->m_flag = 0; | |||||
| m_preDef.push_back(uni); | |||||
| } | } | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniform1i, "setUniform1i(name, ix)") | KX_PYMETHODDEF_DOC(BL_Shader, setUniform1i, "setUniform1i(name, ix)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| if (loc != -1) { | if (loc != -1) { | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformiv(loc, BL_Uniform::UNI_INT, &value, sizeof(int)); | SetUniformiv(loc, RAS_Uniform::UNI_INT, &value, sizeof(int), 1); | ||||
| #else | #else | ||||
| SetUniform(loc, (int)value); | SetUniform(loc, (int)value); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniform2i, "setUniform2i(name, ix, iy)") | KX_PYMETHODDEF_DOC(BL_Shader, setUniform2i, "setUniform2i(name, ix, iy)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| if (loc != -1) { | if (loc != -1) { | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformiv(loc, BL_Uniform::UNI_INT2, array, sizeof(int) * 2); | SetUniformiv(loc, RAS_Uniform::UNI_INT2, array, sizeof(int) * 2, 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array, 2); | SetUniform(loc, array, 2); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") | KX_PYMETHODDEF_DOC(BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| if (loc != -1) { | if (loc != -1) { | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformiv(loc, BL_Uniform::UNI_INT3, array, sizeof(int) * 3); | SetUniformiv(loc, RAS_Uniform::UNI_INT3, array, sizeof(int) * 3, 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array, 3); | SetUniform(loc, array, 3); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ") | KX_PYMETHODDEF_DOC(BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| if (loc != -1) { | if (loc != -1) { | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformiv(loc, BL_Uniform::UNI_INT4, array, sizeof(int) * 4); | SetUniformiv(loc, RAS_Uniform::UNI_INT4, array, sizeof(int) * 4, 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array, 4); | SetUniform(loc, array, 4); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniformfv, "setUniformfv(float (list2 or list3 or list4))") | KX_PYMETHODDEF_DOC(BL_Shader, setUniformfv, "setUniformfv(float (list2 or list3 or list4))") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| { | { | ||||
| float array2[2] = {array_data[0], array_data[1]}; | float array2[2] = {array_data[0], array_data[1]}; | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array2, sizeof(float) * 2); | SetUniformfv(loc, RAS_Uniform::UNI_FLOAT2, array2, sizeof(float) * 2, 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array2, 2); | SetUniform(loc, array2, 2); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| { | { | ||||
| float array3[3] = {array_data[0], array_data[1], array_data[2]}; | float array3[3] = {array_data[0], array_data[1], array_data[2]}; | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array3, sizeof(float) * 3); | SetUniformfv(loc, RAS_Uniform::UNI_FLOAT3, array3, sizeof(float) * 3, 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array3, 3); | SetUniform(loc, array3, 3); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| { | { | ||||
| float array4[4] = {array_data[0], array_data[1], array_data[2], array_data[3]}; | float array4[4] = {array_data[0], array_data[1], array_data[2], array_data[3]}; | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array4, sizeof(float) * 4); | SetUniformfv(loc, RAS_Uniform::UNI_FLOAT4, array4, sizeof(float) * 4, 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array4, 4); | SetUniform(loc, array4, 4); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniformiv, "setUniformiv(uniform_name, (list2 or list3 or list4))") | KX_PYMETHODDEF_DOC(BL_Shader, setUniformiv, "setUniformiv(uniform_name, (list2 or list3 or list4))") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| { | { | ||||
| int array2[2] = {array_data[0], array_data[1]}; | int array2[2] = {array_data[0], array_data[1]}; | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int) * 2); | SetUniformiv(loc, RAS_Uniform::UNI_INT2, array2, sizeof(int) * 2, 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array2, 2); | SetUniform(loc, array2, 2); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| { | { | ||||
| int array3[3] = {array_data[0], array_data[1], array_data[2]}; | int array3[3] = {array_data[0], array_data[1], array_data[2]}; | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int) * 3); | SetUniformiv(loc, RAS_Uniform::UNI_INT3, array3, sizeof(int) * 3, 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array3, 3); | SetUniform(loc, array3, 3); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| { | { | ||||
| int array4[4] = {array_data[0], array_data[1], array_data[2], array_data[3]}; | int array4[4] = {array_data[0], array_data[1], array_data[2], array_data[3]}; | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int) * 4); | SetUniformiv(loc, RAS_Uniform::UNI_INT4, array4, sizeof(int) * 4, 1); | ||||
| #else | #else | ||||
| SetUniform(loc, array4, 4); | SetUniform(loc, array4, 4); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniformMatrix4, | KX_PYMETHODDEF_DOC(BL_Shader, setUniformMatrix4, | ||||
| "setUniformMatrix4(uniform_name, mat-4x4, transpose(row-major=true, col-major=false)") | "setUniformMatrix4(uniform_name, mat-4x4, transpose(row-major=true, col-major=false)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| // Sanity checks done! | // Sanity checks done! | ||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| mat.getValue(matr); | mat.getValue(matr); | ||||
| SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float) * 16), (transp != 0)); | SetUniformfv(loc, RAS_Uniform::UNI_MAT4, matr, (sizeof(float) * 16), 1, (transp != 0)); | ||||
| #else | #else | ||||
| SetUniform(loc, mat, (transp != 0)); | SetUniform(loc, mat, (transp != 0)); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniformMatrix3, | KX_PYMETHODDEF_DOC(BL_Shader, setUniformMatrix3, | ||||
| "setUniformMatrix3(uniform_name, list[3x3], transpose(row-major=true, col-major=false)") | "setUniformMatrix3(uniform_name, list[3x3], transpose(row-major=true, col-major=false)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| #ifdef SORT_UNIFORMS | #ifdef SORT_UNIFORMS | ||||
| mat.getValue3x3(matr); | mat.getValue3x3(matr); | ||||
| SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float) * 9), (transp != 0)); | SetUniformfv(loc, RAS_Uniform::UNI_MAT3, matr, (sizeof(float) * 9), 1, (transp != 0)); | ||||
| #else | #else | ||||
| SetUniform(loc, mat, (transp != 0)); | SetUniform(loc, mat, (transp != 0)); | ||||
| #endif | #endif | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC(BL_Shader, setAttrib, "setAttrib(enum)") | KX_PYMETHODDEF_DOC(BL_Shader, setAttrib, "setAttrib(enum)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| attr = SHD_TANGENT; // user input is ignored for now, there is only 1 attr | attr = SHD_TANGENT; // user input is ignored for now, there is only 1 attr | ||||
| if (mShader == 0) { | if (!m_shader) { | ||||
| PyErr_SetString(PyExc_ValueError, "shader.setAttrib() BL_Shader, invalid shader object"); | PyErr_SetString(PyExc_ValueError, "shader.setAttrib() BL_Shader, invalid shader object"); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| mAttr = attr; | m_attr = attr; | ||||
| glUseProgramObjectARB(mShader); | BindAttribute("Tangent", m_attr); | ||||
| glBindAttribLocationARB(mShader, mAttr, "Tangent"); | |||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC(BL_Shader, setUniformDef, "setUniformDef(name, enum)") | KX_PYMETHODDEF_DOC(BL_Shader, setUniformDef, "setUniformDef(name, enum)") | ||||
| { | { | ||||
| if (mError) { | if (!m_shader) { | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| if (loc != -1) { | if (loc != -1) { | ||||
| bool defined = false; | bool defined = false; | ||||
| BL_UniformVecDef::iterator it = mPreDef.begin(); | RAS_UniformVecDef::iterator it = m_preDef.begin(); | ||||
| while (it != mPreDef.end()) { | while (it != m_preDef.end()) { | ||||
| if ((*it)->mLoc == loc) { | if ((*it)->m_loc == loc) { | ||||
| defined = true; | defined = true; | ||||
| break; | break; | ||||
| } | } | ||||
| Context not available. | |||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| BL_DefUniform *uni = new BL_DefUniform(); | RAS_DefUniform *uni = new RAS_DefUniform(); | ||||
| uni->mLoc = loc; | uni->m_loc = loc; | ||||
| uni->mType = nloc; | uni->m_type = nloc; | ||||
| uni->mFlag = 0; | uni->m_flag = 0; | ||||
| mPreDef.push_back(uni); | m_preDef.push_back(uni); | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| } | } | ||||
| #endif // WITH_PYTHON | #endif // WITH_PYTHON | ||||
| // eof | |||||
| Context not available. | |||||