blender/source/gameengine/Ketsji/BL_Shader.cpp
2007-05-29 07:46:07 +00:00

1471 lines
30 KiB
C++

#ifdef WIN32
#include <windows.h>
#endif // WIN32
#ifdef __APPLE__
#define GL_GLEXT_LEGACY 1
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#include <iostream>
#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"
#include "RAS_MeshObject.h"
#include "RAS_IRasterizer.h"
//using namespace bgl;
#define spit(x) std::cout << x << std::endl;
#define SORT_UNIFORMS 1
#define UNIFORM_MAX_LEN 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(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=0;
}
#endif
}
void BL_Uniform::Apply(class BL_Shader *shader)
{
#ifdef GL_ARB_shader_objects
#ifdef SORT_UNIFORMS
MT_assert(mType > UNI_NONE && mType < UNI_MAX && mData);
if(!mDirty)
return;
switch(mType)
{
case UNI_FLOAT: {
float *f = (float*)mData;
bgl::blUniform1fARB(mLoc,(GLfloat)*f);
}break;
case UNI_INT: {
int *f = (int*)mData;
bgl::blUniform1iARB(mLoc, (GLint)*f);
}break;
case UNI_FLOAT2: {
float *f = (float*)mData;
bgl::blUniform2fvARB(mLoc,1, (GLfloat*)f);
}break;
case UNI_FLOAT3: {
float *f = (float*)mData;
bgl::blUniform3fvARB(mLoc,1,(GLfloat*)f);
}break;
case UNI_FLOAT4: {
float *f = (float*)mData;
bgl::blUniform4fvARB(mLoc,1,(GLfloat*)f);
}break;
case UNI_INT2: {
int *f = (int*)mData;
bgl::blUniform2ivARB(mLoc,1,(GLint*)f);
}break;
case UNI_INT3: {
int *f = (int*)mData;
bgl::blUniform3ivARB(mLoc,1,(GLint*)f);
}break;
case UNI_INT4: {
int *f = (int*)mData;
bgl::blUniform4ivARB(mLoc,1,(GLint*)f);
}break;
case UNI_MAT4: {
float *f = (float*)mData;
bgl::blUniformMatrix4fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f);
}break;
case UNI_MAT3: {
float *f = (float*)mData;
bgl::blUniformMatrix3fvARB(mLoc, 1, mTranspose?GL_TRUE:GL_FALSE,(GLfloat*)f);
}break;
}
mDirty = false;
#endif
#endif
}
void BL_Uniform::SetData(int location, int type,bool transpose)
{
#ifdef SORT_UNIFORMS
mType = type;
mLoc = location;
mDirty = true;
#endif
}
const bool BL_Shader::Ok()const
{
return (mShader !=0 && mOk && mUse);
}
BL_Shader::BL_Shader(PyTypeObject *T)
: PyObjectPlus(T),
mShader(0),
mPass(1),
mOk(0),
mUse(0),
mAttr(0),
vertProg(""),
fragProg(""),
mError(0),
mDirty(true)
{
// if !RAS_EXT_support._ARB_shader_objects this class will not be used
//for (int i=0; i<MAXTEX; i++) {
// mSampler[i] = BL_Sampler();
//}
}
using namespace bgl;
BL_Shader::~BL_Shader()
{
#ifdef GL_ARB_shader_objects
//for (int i=0; i<MAXTEX; i++){
// if(mSampler[i].mOwn) {
// if(mSampler[i].mTexture)
// mSampler[i].mTexture->DeleteTex();
// }
//}
ClearUniforms();
if( mShader ) {
bgl::blDeleteObjectARB(mShader);
mShader = 0;
}
vertProg = 0;
fragProg = 0;
mOk = 0;
bgl::blUseProgramObjectARB(0);
#endif//GL_ARB_shader_objects
}
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 0;
}
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
if(!mDirty)
return;
for(unsigned int i=0; i<mUniforms.size(); i++)
mUniforms[i]->Apply(this);
mDirty = false;
#endif
}
void BL_Shader::UnloadShader()
{
//
}
bool BL_Shader::LinkProgram()
{
#ifdef GL_ARB_shader_objects
int vertlen = 0, fraglen=0, proglen=0;
int vertstatus=0, fragstatus=0, progstatus=0;
unsigned int tmpVert=0, tmpFrag=0, tmpProg=0;
int char_len=0;
char *logInf =0;
if(mError)
goto programError;
if(!vertProg || !fragProg){
spit("Invalid GLSL sources");
return false;
}
if( !RAS_EXT_support._ARB_fragment_shader) {
spit("Fragment shaders not supported");
return false;
}
if( !RAS_EXT_support._ARB_vertex_shader) {
spit("Vertex shaders not supported");
return false;
}
// -- vertex shader ------------------
tmpVert = bgl::blCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
bgl::blShaderSourceARB(tmpVert, 1, (const char**)&vertProg, 0);
bgl::blCompileShaderARB(tmpVert);
bgl::blGetObjectParameterivARB(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");
bgl::blGetInfoLogARB(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
bgl::blGetObjectParameterivARB(tmpVert, GL_OBJECT_COMPILE_STATUS_ARB,(GLint*)&vertstatus);
if(!vertstatus) {
spit("---- Vertex shader failed to compile ----");
goto programError;
}
// -- fragment shader ----------------
tmpFrag = bgl::blCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
bgl::blShaderSourceARB(tmpFrag, 1,(const char**)&fragProg, 0);
bgl::blCompileShaderARB(tmpFrag);
bgl::blGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &fraglen);
if(fraglen >0 && fraglen < MAX_LOG_LEN){
logInf = (char*)MEM_mallocN(fraglen, "frag-log");
bgl::blGetInfoLogARB(tmpFrag, fraglen,(GLsizei*) &char_len, logInf);
if(char_len >0) {
spit("---- Fragment Shader Error ----");
spit(logInf);
}
MEM_freeN(logInf);
logInf=0;
}
bgl::blGetObjectParameterivARB(tmpFrag, GL_OBJECT_COMPILE_STATUS_ARB, (GLint*) &fragstatus);
if(!fragstatus){
spit("---- Fragment shader failed to compile ----");
goto programError;
}
// -- program ------------------------
// set compiled vert/frag shader & link
tmpProg = bgl::blCreateProgramObjectARB();
bgl::blAttachObjectARB(tmpProg, tmpVert);
bgl::blAttachObjectARB(tmpProg, tmpFrag);
bgl::blLinkProgramARB(tmpProg);
bgl::blGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &proglen);
bgl::blGetObjectParameterivARB(tmpProg, GL_OBJECT_LINK_STATUS_ARB, (GLint*) &progstatus);
if(proglen > 0 && proglen < MAX_LOG_LEN) {
logInf = (char*)MEM_mallocN(proglen, "prog-log");
bgl::blGetInfoLogARB(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;
bgl::blDeleteObjectARB(tmpVert);
bgl::blDeleteObjectARB(tmpFrag);
mOk = 1;
mError = 0;
return true;
programError:
if(tmpVert) {
bgl::blDeleteObjectARB(tmpVert);
tmpVert=0;
}
if(tmpFrag) {
bgl::blDeleteObjectARB(tmpFrag);
tmpFrag=0;
}
if(tmpProg) {
bgl::blDeleteObjectARB(tmpProg);
tmpProg=0;
}
mOk = 0;
mUse = 0;
mError = 1;
return false;
#else
return false;
#endif//GL_ARB_shader_objects
}
const char *BL_Shader::GetVertPtr()
{
return vertProg?vertProg:0;
}
const 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;
}
//
//const BL_Sampler* BL_Shader::GetSampler(int i)
//{
// MT_assert(i<=MAXTEX);
// return &mSampler[i];
//}
void BL_Shader::SetSampler(int loc, int unit)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
bgl::blUniform1iARB(loc, unit);
}
#endif
}
//
//void BL_Shader::InitializeSampler(int unit, BL_Texture* texture)
//{
// MT_assert(unit<=MAXTEX);
// mSampler[unit].mTexture = texture;
// mSampler[unit].mLoc =-1;
// mSampler[unit].mOwn = 0;
//}
void BL_Shader::SetProg(bool enable)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
if( mShader != 0 && mOk && enable) {
bgl::blUseProgramObjectARB(mShader);
}
else {
bgl::blUseProgramObjectARB(0);
}
}
#endif
}
void BL_Shader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty )
{
#ifdef GL_ARB_shader_objects
if(!Ok() || !mPreDef.size())
return;
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
MT_Matrix4x4 model;
model.setValue(ms.m_OpenGLMatrix);
MT_Matrix4x4 view;
rasty->GetViewMatrix(view);
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:
{
view.invert();
SetUniform(uni->mLoc, view);
break;
}
case VIEWMATRIX_INVERSETRANSPOSE:
{
view.invert();
SetUniform(uni->mLoc, view, true);
break;
}
case CONSTANT_TIMER:
{
SetUniform(uni->mLoc, (float)rasty->GetTime());
break;
}
default:
break;
}
}
}
#endif
}
int BL_Shader::GetAttribLocation(const STR_String& name)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
return bgl::blGetAttribLocationARB(mShader, name.ReadPtr());
}
#endif
return -1;
}
void BL_Shader::BindAttribute(const STR_String& attr, int loc)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
bgl::blBindAttribLocationARB(mShader, loc, attr.ReadPtr());
}
#endif
}
int BL_Shader::GetUniformLocation(const STR_String& name)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
MT_assert(mShader!=0);
int location = bgl::blGetUniformLocationARB(mShader, name.ReadPtr());
if(location == -1)
spit("Invalid uniform value: " << name.ReadPtr() << ".");
return location;
}
#endif
return -1;
}
void BL_Shader::SetUniform(int uniform, const MT_Tuple2& vec)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
float value[2];
vec.getValue(value);
bgl::blUniform2fvARB(uniform, 1, value);
}
#endif
}
void BL_Shader::SetUniform(int uniform, const MT_Tuple3& vec)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
float value[3];
vec.getValue(value);
bgl::blUniform3fvARB(uniform, 1, value);
}
#endif
}
void BL_Shader::SetUniform(int uniform, const MT_Tuple4& vec)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
float value[4];
vec.getValue(value);
bgl::blUniform4fvARB(uniform, 1, value);
}
#endif
}
void BL_Shader::SetUniform(int uniform, const unsigned int& val)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
bgl::blUniform1iARB(uniform, val);
}
#endif
}
void BL_Shader::SetUniform(int uniform, const int val)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
bgl::blUniform1iARB(uniform, val);
}
#endif
}
void BL_Shader::SetUniform(int uniform, const float& val)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
bgl::blUniform1fARB(uniform, val);
}
#endif
}
void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4& vec, bool transpose)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
float value[16];
vec.getValue(value);
bgl::blUniformMatrix4fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
}
#endif
}
void BL_Shader::SetUniform(int uniform, const MT_Matrix3x3& vec, bool transpose)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
float value[9];
value[0] = (float)vec[0][0]; value[1] = (float)vec[1][0]; value[2] = (float)vec[2][0];
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[7] = (float)vec[2][2];
bgl::blUniformMatrix3fvARB(uniform, 1, transpose?GL_TRUE:GL_FALSE, value);
}
#endif
}
void BL_Shader::SetUniform(int uniform, const float* val, int len)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
if(len == 2)
bgl::blUniform2fvARB(uniform, 1,(GLfloat*)val);
else if (len == 3)
bgl::blUniform3fvARB(uniform, 1,(GLfloat*)val);
else if (len == 4)
bgl::blUniform4fvARB(uniform, 1,(GLfloat*)val);
else
MT_assert(0);
}
#endif
}
void BL_Shader::SetUniform(int uniform, const int* val, int len)
{
#ifdef GL_ARB_shader_objects
if( RAS_EXT_support._ARB_fragment_shader &&
RAS_EXT_support._ARB_vertex_shader &&
RAS_EXT_support._ARB_shader_objects
)
{
if(len == 2)
bgl::blUniform2ivARB(uniform, 1, (GLint*)val);
else if (len == 3)
bgl::blUniform3ivARB(uniform, 1, (GLint*)val);
else if (len == 4)
bgl::blUniform4ivARB(uniform, 1, (GLint*)val);
else
MT_assert(0);
}
#endif
}
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, setAttrib ),
KX_PYMETHODTABLE( BL_Shader, setUniformfv ),
KX_PYMETHODTABLE( BL_Shader, setUniformiv ),
KX_PYMETHODTABLE( BL_Shader, setUniformDef ),
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;
Py_Return;
}
return NULL;
#else
Py_Return;
#endif
}
KX_PYMETHODDEF_DOC( BL_Shader, delSource, "delSource( )" )
{
#ifdef GL_ARB_shader_objects
ClearUniforms();
bgl::blUseProgramObjectARB(0);
bgl::blDeleteObjectARB(mShader);
mShader = 0;
mOk = 0;
mUse = 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(mError) {
Py_INCREF(Py_None);
return Py_None;
}
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,(GLint*) &stat);
if(stat > 0 && stat < MAX_LOG_LEN) {
int char_len=0;
char *logInf = (char*)MEM_mallocN(stat, "validate-log");
bgl::blGetInfoLogARB(mShader, stat,(GLsizei*) &char_len, logInf);
if(char_len >0) {
spit("---- GLSL Validation ----");
spit(logInf);
}
MEM_freeN(logInf);
logInf=0;
}
#endif//GL_ARB_shader_objects
Py_Return;
}
KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" )
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
int index=-1;
if(PyArg_ParseTuple(args, "si", &uniform, &index))
{
int loc = GetUniformLocation(uniform);
if(loc != -1) {
if(index >= MAXTEX && index < 0)
spit("Invalid texture sample index: " << index);
#ifdef SORT_UNIFORMS
SetUniformiv(loc, BL_Uniform::UNI_INT, &index, (sizeof(int)) );
#else
SetUniform(loc, index);
#endif
//if(index <= MAXTEX)
// mSampler[index].mLoc = loc;
//else
// spit("Invalid texture sample index: " << index);
}
Py_Return;
}
return NULL;
}
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)" )
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
float value=0;
if(PyArg_ParseTuple(args, "sf", &uniform, &value ))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT, &value, sizeof(float));
#else
SetUniform( loc, (float)value );
#endif
}
Py_Return;
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f , "setUniform2f(name, fx, fy)")
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
float array[2]={ 0,0 };
if(PyArg_ParseTuple(args, "sff", &uniform, &array[0],&array[1] ))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array, (sizeof(float)*2) );
#else
SetUniform(loc, array, 2);
#endif
}
Py_Return;
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
float array[3]={0,0,0};
if(PyArg_ParseTuple(args, "sfff", &uniform, &array[0],&array[1],&array[2]))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array, (sizeof(float)*3) );
#else
SetUniform(loc, array, 3);
#endif
}
Py_Return;
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
float array[4]={0,0,0,0};
if(PyArg_ParseTuple(args, "sffff", &uniform, &array[0],&array[1],&array[2], &array[3]))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array, (sizeof(float)*4) );
#else
SetUniform(loc, array, 4);
#endif
}
Py_Return;
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" )
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
int value=0;
if(PyArg_ParseTuple(args, "si", &uniform, &value ))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
#ifdef SORT_UNIFORMS
SetUniformiv(loc, BL_Uniform::UNI_INT, &value, sizeof(int));
#else
SetUniform(loc, (int)value);
#endif
}
Py_Return;
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i , "setUniform2i(name, ix, iy)")
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
int array[2]={ 0,0 };
if(PyArg_ParseTuple(args, "sii", &uniform, &array[0],&array[1] ))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
#ifdef SORT_UNIFORMS
SetUniformiv(loc, BL_Uniform::UNI_INT2, array, sizeof(int)*2);
#else
SetUniform(loc, array, 2);
#endif
}
Py_Return;
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
int array[3]={0,0,0};
if(PyArg_ParseTuple(args, "siii", &uniform, &array[0],&array[1],&array[2]))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
#ifdef SORT_UNIFORMS
SetUniformiv(loc, BL_Uniform::UNI_INT3, array, sizeof(int)*3);
#else
SetUniform(loc, array, 3);
#endif
}
Py_Return;
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
int array[4]={0,0,0, 0};
if(PyArg_ParseTuple(args, "siiii", &uniform, &array[0],&array[1],&array[2], &array[3] ))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
#ifdef SORT_UNIFORMS
SetUniformiv(loc, BL_Uniform::UNI_INT4, array, sizeof(int)*4);
#else
SetUniform(loc, array, 4);
#endif
}
Py_Return;
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniformfv , "setUniformfv( float (list2 or list3 or list4) )")
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char*uniform = "";
PyObject *listPtr =0;
float array_data[4] = {0.f,0.f,0.f,0.f};
if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
if(PySequence_Check(listPtr))
{
unsigned int list_size = PySequence_Size(listPtr);
for(unsigned int i=0; (i<list_size && i<4); i++)
{
PyObject *item = PySequence_GetItem(listPtr, i);
array_data[i] = (float)PyFloat_AsDouble(item);
Py_DECREF(item);
}
switch(list_size)
{
case 2:
{
float array2[2] = { array_data[0],array_data[1] };
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT2, array2, sizeof(float)*2);
#else
SetUniform(loc, array2, 2);
#endif
Py_Return;
} break;
case 3:
{
float array3[3] = { array_data[0],array_data[1],array_data[2] };
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT3, array3, sizeof(float)*3);
#else
SetUniform(loc, array3, 3);
#endif
Py_Return;
}break;
case 4:
{
float array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT4, array4, sizeof(float)*4);
#else
SetUniform(loc, array4, 4);
#endif
Py_Return;
}break;
default:
{
PyErr_Format(PyExc_TypeError, "Invalid list size");
return NULL;
}break;
}
}
}
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniformiv, "setUniformiv( int (list2 or list3 or list4) )")
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char*uniform = "";
PyObject *listPtr =0;
int array_data[4] = {0,0,0,0};
if(PyArg_ParseTuple(args, "sO", &uniform, &listPtr))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
if(PySequence_Check(listPtr))
{
unsigned int list_size = PySequence_Size(listPtr);
for(unsigned int i=0; (i<list_size && i<4); i++)
{
PyObject *item = PySequence_GetItem(listPtr, i);
array_data[i] = PyInt_AsLong(item);
Py_DECREF(item);
}
switch(list_size)
{
case 2:
{
int array2[2] = { array_data[0],array_data[1]};
#ifdef SORT_UNIFORMS
SetUniformiv(loc, BL_Uniform::UNI_INT2, array2, sizeof(int)*2);
#else
SetUniform(loc, array2, 2);
#endif
Py_Return;
} break;
case 3:
{
int array3[3] = { array_data[0],array_data[1],array_data[2] };
#ifdef SORT_UNIFORMS
SetUniformiv(loc, BL_Uniform::UNI_INT3, array3, sizeof(int)*3);
#else
SetUniform(loc, array3, 3);
#endif
Py_Return;
}break;
case 4:
{
int array4[4] = { array_data[0],array_data[1],array_data[2],array_data[3] };
#ifdef SORT_UNIFORMS
SetUniformiv(loc, BL_Uniform::UNI_INT4, array4, sizeof(int)*4);
#else
SetUniform(loc, array4, 4);
#endif
Py_Return;
}break;
default:
{
PyErr_Format(PyExc_TypeError, "Invalid list size");
return NULL;
}break;
}
}
}
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4,
"setUniformMatrix4(uniform-name, mat-4x4, transpose(row-major=true, col-major=false)" )
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
float matr[16] = {
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
};
char *uniform="";
PyObject *matrix=0;
int transp=1; // MT_ is row major so transpose by default....
if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
if (PyObject_IsMT_Matrix(matrix, 4))
{
MT_Matrix4x4 mat;
if (PyMatTo(matrix, mat))
{
#ifdef SORT_UNIFORMS
mat.getValue(matr);
SetUniformfv(loc, BL_Uniform::UNI_MAT4, matr, (sizeof(float)*16), (transp!=0) );
#else
SetUniform(loc,mat,(transp!=0));
#endif
Py_Return;
}
}
}
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3,
"setUniformMatrix3(uniform-name, list[3x3], transpose(row-major=true, col-major=false)" )
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
float matr[9] = {
1,0,0,
0,1,0,
0,0,1,
};
char *uniform="";
PyObject *matrix=0;
int transp=1; // MT_ is row major so transpose by default....
if(PyArg_ParseTuple(args, "sO|i",&uniform, &matrix,&transp))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
if (PyObject_IsMT_Matrix(matrix, 3))
{
MT_Matrix3x3 mat;
if (PyMatTo(matrix, mat))
{
#ifdef SORT_UNIFORMS
mat.getValue(matr);
SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float)*9), (transp!=0) );
#else
SetUniform(loc,mat,(transp!=0));
#endif
Py_Return;
}
}
}
}
return NULL;
}
KX_PYMETHODDEF_DOC( BL_Shader, setAttrib, "setAttrib(enum)" )
{
#ifdef GL_ARB_shader_objects
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
int attr=0;
if(PyArg_ParseTuple(args, "i", &attr )) {
if(mShader==0) {
PyErr_Format(PyExc_ValueError, "invalid shader object");
return NULL;
}
mAttr=SHD_TANGENT;
bgl::blUseProgramObjectARB(mShader);
bgl::blBindAttribLocationARB(mShader, mAttr, "Tangent");
Py_Return;
}
return NULL;
#endif
}
KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" )
{
if(mError) {
Py_INCREF(Py_None);
return Py_None;
}
char *uniform="";
int nloc=0;
if(PyArg_ParseTuple(args, "si",&uniform, &nloc))
{
int loc = GetUniformLocation(uniform);
if(loc != -1)
{
bool defined = false;
BL_UniformVecDef::iterator it = mPreDef.begin();
while(it != mPreDef.end()) {
if((*it)->mLoc == loc) {
defined = true;
break;
}
it++;
}
if(defined)
{
Py_Return;
}
BL_DefUniform *uni = new BL_DefUniform();
uni->mLoc = loc;
uni->mType = nloc;
uni->mFlag = 0;
mPreDef.push_back(uni);
Py_Return;
}
}
return NULL;
}
// eof