964107fbce
This class did nothing but print out extensions if they were found. Instead, the code from bge.logic.PrintGLInfo() is now printed as the Rasterizer is initialized. This gives better information, and it removes some GL code from KX_PythonInit.cpp (the PrintGLInfo method now calls the Rasterizer to print the information). Differential Revision: https://developer.blender.org/D438
1437 lines
31 KiB
C++
1437 lines
31 KiB
C++
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
/** \file gameengine/Ketsji/BL_Shader.cpp
|
|
* \ingroup ketsji
|
|
*/
|
|
|
|
#include "glew-mx.h"
|
|
|
|
#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_MeshObject.h"
|
|
#include "RAS_IRasterizer.h"
|
|
|
|
#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
|
|
}
|
|
|
|
void BL_Uniform::Apply(class BL_Shader *shader)
|
|
{
|
|
#ifdef SORT_UNIFORMS
|
|
MT_assert(mType > UNI_NONE && mType < UNI_MAX && mData);
|
|
|
|
if (!mDirty) {
|
|
return;
|
|
}
|
|
|
|
switch (mType) {
|
|
case UNI_FLOAT:
|
|
{
|
|
float *f = (float *)mData;
|
|
glUniform1fARB(mLoc, (GLfloat)*f);
|
|
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;
|
|
}
|
|
}
|
|
mDirty = false;
|
|
#endif
|
|
}
|
|
|
|
void BL_Uniform::SetData(int location, int type, bool transpose)
|
|
{
|
|
#ifdef SORT_UNIFORMS
|
|
mType = type;
|
|
mLoc = location;
|
|
mDirty = true;
|
|
#endif
|
|
}
|
|
|
|
bool BL_Shader::Ok()const
|
|
{
|
|
return (mShader != 0 && mOk && mUse);
|
|
}
|
|
|
|
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
|
|
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()
|
|
{
|
|
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 = 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;
|
|
}
|
|
|
|
// -- 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;
|
|
}
|
|
|
|
// -- 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;
|
|
}
|
|
|
|
// -- program ------------------------
|
|
// set compiled vert/frag shader & link
|
|
tmpProg = glCreateProgramObjectARB();
|
|
glAttachObjectARB(tmpProg, tmpVert);
|
|
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;
|
|
glDeleteObjectARB(tmpVert);
|
|
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;
|
|
}
|
|
|
|
mOk = 0;
|
|
mUse = 0;
|
|
mError = 1;
|
|
return false;
|
|
}
|
|
|
|
const char *BL_Shader::GetVertPtr()
|
|
{
|
|
return vertProg ? vertProg : NULL;
|
|
}
|
|
|
|
const char *BL_Shader::GetFragPtr()
|
|
{
|
|
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()
|
|
{
|
|
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)
|
|
{
|
|
if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) {
|
|
glUniform1iARB(loc, unit);
|
|
}
|
|
}
|
|
|
|
//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)
|
|
{
|
|
if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_ARB_shader_objects) {
|
|
if (mShader != 0 && mOk && enable) {
|
|
glUseProgramObjectARB(mShader);
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
|
|
void BL_Shader::SetUniform(int uniform, const MT_Matrix4x4 &vec, bool transpose)
|
|
{
|
|
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)
|
|
{
|
|
if (GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && GLEW_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[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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BL_Shader::SetUniform(int uniform, const int *val, int len)
|
|
{
|
|
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
|
|
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
|
|
};
|
|
|
|
PyAttributeDef BL_Shader::Attributes[] = {
|
|
{NULL} //Sentinel
|
|
};
|
|
|
|
PyTypeObject BL_Shader::Type = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
"BL_Shader",
|
|
sizeof(PyObjectPlus_Proxy),
|
|
0,
|
|
py_base_dealloc,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
py_base_repr,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
Methods,
|
|
0,
|
|
0,
|
|
&PyObjectPlus::Type,
|
|
0, 0, 0, 0, 0, 0,
|
|
py_base_new
|
|
};
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setSource, " setSource(vertexProgram, fragmentProgram)")
|
|
{
|
|
if (mShader != 0 && mOk) {
|
|
// already set...
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
char *v, *f;
|
|
int apply = 0;
|
|
|
|
if (PyArg_ParseTuple(args, "ssi:setSource", &v, &f, &apply)) {
|
|
vertProg = v;
|
|
fragProg = f;
|
|
|
|
if (LinkProgram()) {
|
|
glUseProgramObjectARB(mShader);
|
|
mUse = apply != 0;
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
vertProg = NULL;
|
|
fragProg = NULL;
|
|
mUse = 0;
|
|
Py_RETURN_NONE;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, delSource, "delSource( )")
|
|
{
|
|
ClearUniforms();
|
|
glUseProgramObjectARB(0);
|
|
glDeleteObjectARB(mShader);
|
|
mShader = 0;
|
|
mOk = 0;
|
|
mUse = 0;
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, isValid, "isValid()")
|
|
{
|
|
return PyBool_FromLong((mShader != 0 && mOk));
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, getVertexProg, "getVertexProg( )")
|
|
{
|
|
return PyUnicode_FromString(vertProg ? vertProg : "");
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, getFragmentProg, "getFragmentProg( )")
|
|
{
|
|
return PyUnicode_FromString(fragProg ? fragProg : "");
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, validate, "validate()")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
if (mShader == 0) {
|
|
PyErr_SetString(PyExc_TypeError, "shader.validate(): BL_Shader, invalid shader object");
|
|
return NULL;
|
|
}
|
|
|
|
int stat = 0;
|
|
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;
|
|
}
|
|
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setSampler, "setSampler(name, index)")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
int index = -1;
|
|
|
|
if (PyArg_ParseTuple(args, "si:setSampler", &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_NONE;
|
|
}
|
|
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
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniform1f, "setUniform1f(name, fx)")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
float value = 0.0f;
|
|
|
|
if (PyArg_ParseTuple(args, "sf:setUniform1f", &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_NONE;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniform2f, "setUniform2f(name, fx, fy)")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
float array[2] = {0.0f, 0.0f};
|
|
|
|
if (PyArg_ParseTuple(args, "sff:setUniform2f", &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_NONE;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
float array[3] = {0.0f, 0.0f, 0.0f};
|
|
|
|
if (PyArg_ParseTuple(args, "sfff:setUniform3f", &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_NONE;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
float array[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
|
|
if (PyArg_ParseTuple(args, "sffff:setUniform4f", &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_NONE;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniform1i, "setUniform1i(name, ix)")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
int value = 0;
|
|
|
|
if (PyArg_ParseTuple(args, "si:setUniform1i", &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_NONE;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniform2i, "setUniform2i(name, ix, iy)")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
int array[2] = {0, 0};
|
|
|
|
if (PyArg_ParseTuple(args, "sii:setUniform2i", &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_NONE;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
int array[3] = {0, 0, 0};
|
|
|
|
if (PyArg_ParseTuple(args, "siii:setUniform3i", &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_NONE;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) ")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
int array[4] = {0, 0, 0, 0};
|
|
|
|
if (PyArg_ParseTuple(args, "siiii:setUniform4i", &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_NONE;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniformfv, "setUniformfv(float (list2 or list3 or list4))")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform = "";
|
|
PyObject *listPtr = NULL;
|
|
float array_data[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
|
|
if (PyArg_ParseTuple(args, "sO:setUniformfv", &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_NONE;
|
|
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_NONE;
|
|
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_NONE;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"shader.setUniform4i(name, ix,iy,iz, iw): BL_Shader. invalid list size");
|
|
return NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniformiv, "setUniformiv(uniform_name, (list2 or list3 or list4))")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform = "";
|
|
PyObject *listPtr = NULL;
|
|
int array_data[4] = {0, 0, 0, 0};
|
|
|
|
if (!PyArg_ParseTuple(args, "sO:setUniformiv", &uniform, &listPtr)) {
|
|
return NULL;
|
|
}
|
|
|
|
int loc = GetUniformLocation(uniform);
|
|
|
|
if (loc == -1) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"shader.setUniformiv(...): BL_Shader, first string argument is not a valid uniform value");
|
|
return NULL;
|
|
}
|
|
|
|
if (!PySequence_Check(listPtr)) {
|
|
PyErr_SetString(PyExc_TypeError, "shader.setUniformiv(...): BL_Shader, second argument is not a sequence");
|
|
return NULL;
|
|
}
|
|
|
|
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] = PyLong_AsLong(item);
|
|
Py_DECREF(item);
|
|
}
|
|
|
|
if (PyErr_Occurred()) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"shader.setUniformiv(...): BL_Shader, one or more values in the list is not an int");
|
|
return NULL;
|
|
}
|
|
|
|
// Sanity checks done!
|
|
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_NONE;
|
|
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_NONE;
|
|
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_NONE;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"shader.setUniformiv(...): BL_Shader, second argument, invalid list size, expected an int "
|
|
"list between 2 and 4");
|
|
return NULL;
|
|
break;
|
|
}
|
|
}
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniformMatrix4,
|
|
"setUniformMatrix4(uniform_name, mat-4x4, transpose(row-major=true, col-major=false)")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
float matr[16] = {
|
|
1.0f, 0.0f, 0.0f, 0.0f,
|
|
0.0f, 1.0f, 0.0f, 0.0f,
|
|
0.0f, 0.0f, 1.0f, 0.0f,
|
|
0.0f, 0.0f, 0.0f, 1.0f
|
|
};
|
|
|
|
const char *uniform;
|
|
PyObject *matrix = NULL;
|
|
int transp = 0; // python use column major by default, so no transpose....
|
|
|
|
if (!PyArg_ParseTuple(args, "sO|i:setUniformMatrix4", &uniform, &matrix, &transp)) {
|
|
return NULL;
|
|
}
|
|
|
|
int loc = GetUniformLocation(uniform);
|
|
|
|
if (loc == -1) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"shader.setUniformMatrix4(...): BL_Shader, first string argument is not a valid uniform value");
|
|
return NULL;
|
|
}
|
|
|
|
MT_Matrix4x4 mat;
|
|
|
|
if (!PyMatTo(matrix, mat)) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"shader.setUniformMatrix4(...): BL_Shader, second argument cannot be converted into a 4x4 matrix");
|
|
return NULL;
|
|
}
|
|
|
|
// Sanity checks done!
|
|
#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_NONE;
|
|
}
|
|
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniformMatrix3,
|
|
"setUniformMatrix3(uniform_name, list[3x3], transpose(row-major=true, col-major=false)")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
float matr[9] = {
|
|
1.0f, 0.0f, 0.0f,
|
|
0.0f, 1.0f, 0.0f,
|
|
0.0f, 0.0f, 1.0f,
|
|
};
|
|
|
|
const char *uniform;
|
|
PyObject *matrix = NULL;
|
|
int transp = 0; // python use column major by default, so no transpose....
|
|
|
|
if (!PyArg_ParseTuple(args, "sO|i:setUniformMatrix3", &uniform, &matrix, &transp)) {
|
|
return NULL;
|
|
}
|
|
|
|
int loc = GetUniformLocation(uniform);
|
|
|
|
if (loc == -1) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"shader.setUniformMatrix3(...): BL_Shader, first string argument is not a valid uniform value");
|
|
return NULL;
|
|
}
|
|
|
|
MT_Matrix3x3 mat;
|
|
|
|
if (!PyMatTo(matrix, mat)) {
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"shader.setUniformMatrix3(...): BL_Shader, second argument cannot be converted into a 3x3 matrix");
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef SORT_UNIFORMS
|
|
mat.getValue3x3(matr);
|
|
SetUniformfv(loc, BL_Uniform::UNI_MAT3, matr, (sizeof(float) * 9), (transp != 0));
|
|
#else
|
|
SetUniform(loc, mat, (transp != 0));
|
|
#endif
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setAttrib, "setAttrib(enum)")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
int attr = 0;
|
|
|
|
if (!PyArg_ParseTuple(args, "i:setAttrib", &attr)) {
|
|
return NULL;
|
|
}
|
|
|
|
attr = SHD_TANGENT; // user input is ignored for now, there is only 1 attr
|
|
|
|
if (mShader == 0) {
|
|
PyErr_SetString(PyExc_ValueError, "shader.setAttrib() BL_Shader, invalid shader object");
|
|
return NULL;
|
|
}
|
|
|
|
mAttr = attr;
|
|
glUseProgramObjectARB(mShader);
|
|
glBindAttribLocationARB(mShader, mAttr, "Tangent");
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
|
|
KX_PYMETHODDEF_DOC(BL_Shader, setUniformDef, "setUniformDef(name, enum)")
|
|
{
|
|
if (mError) {
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
const char *uniform;
|
|
int nloc = 0;
|
|
if (PyArg_ParseTuple(args, "si:setUniformDef", &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_NONE;
|
|
}
|
|
|
|
BL_DefUniform *uni = new BL_DefUniform();
|
|
uni->mLoc = loc;
|
|
uni->mType = nloc;
|
|
uni->mFlag = 0;
|
|
mPreDef.push_back(uni);
|
|
Py_RETURN_NONE;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#endif // WITH_PYTHON
|
|
|
|
// eof
|