BL_Shader.setUniformEyef(name)

defines a uniform that reflects the eye being rendered in stereo mode:
    0.0 for the left eye, 0.5 for the right eye.
    In non stereo mode, the value of the uniform is fixed to 0.0.
    The typical use of this uniform is in stereo mode to sample stereo textures
    containing the left and right eye images in a top-bottom order.

    python:
      shader = obj.meshes[0].materials[mat].getShader()
      shader.setUniformEyef("eye")

    shader:
      uniform float eye;
      uniform sampler2D tex;
      void main(void)
      {
         vec4 color;
         float ty, tx;
         tx = gl_TexCoord[0].x;
         ty = eye+gl_TexCoord[0].y*0.5;
         // ty will be between 0 and 0.5 for the left eye render
         // and 0.5 and 1.0 for the right eye render.
         color = texture(tex, vec2(tx, ty));
         ...
      }
This commit is contained in:
Benoit Bolsee
2016-06-10 00:28:19 +02:00
parent fa9bb2ffe9
commit c0bf881ebf
3 changed files with 112 additions and 58 deletions

View File

@@ -214,6 +214,16 @@ base class --- :class:`PyObjectPlus`
:arg iList: a list (2, 3 or 4 elements) of integer values :arg iList: a list (2, 3 or 4 elements) of integer values
:type iList: list[integer] :type iList: list[integer]
.. method:: setUniformEyef(name)
Set a uniform with a float value that reflects the eye being render in stereo mode:
0.0 for the left eye, 0.5 for the right eye. In non stereo mode, the value of the uniform
is fixed to 0.0. The typical use of this uniform is in stereo mode to sample stereo textures
containing the left and right eye images in a top-bottom order.
:arg name: the uniform name
:type name: string
.. method:: validate() .. method:: validate()
Validate the shader object. Validate the shader object.

View File

@@ -32,6 +32,7 @@
#include "MT_Matrix4x4.h" #include "MT_Matrix4x4.h"
#include "MT_Matrix3x3.h" #include "MT_Matrix3x3.h"
#include "KX_PyMath.h" #include "KX_PyMath.h"
#include "KX_PythonInit.h"
#include "MEM_guardedalloc.h" #include "MEM_guardedalloc.h"
#include "RAS_MeshObject.h" #include "RAS_MeshObject.h"
@@ -67,15 +68,16 @@ BL_Uniform::~BL_Uniform()
#endif #endif
} }
void BL_Uniform::Apply(class BL_Shader *shader) bool BL_Uniform::Apply(class BL_Shader *shader)
{ {
#ifdef SORT_UNIFORMS #ifdef SORT_UNIFORMS
RAS_IRasterizer *ras;
MT_assert(mType > UNI_NONE && mType < UNI_MAX && mData); MT_assert(mType > UNI_NONE && mType < UNI_MAX && mData);
if (!mDirty) { if (!mDirty)
return; return false;
}
mDirty = false;
switch (mType) { switch (mType) {
case UNI_FLOAT: case UNI_FLOAT:
{ {
@@ -83,6 +85,15 @@ void BL_Uniform::Apply(class BL_Shader *shader)
glUniform1fARB(mLoc, (GLfloat)*f); glUniform1fARB(mLoc, (GLfloat)*f);
break; 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: case UNI_INT:
{ {
int *f = (int *)mData; int *f = (int *)mData;
@@ -138,7 +149,7 @@ void BL_Uniform::Apply(class BL_Shader *shader)
break; break;
} }
} }
mDirty = false; return mDirty;
#endif #endif
} }
@@ -274,11 +285,10 @@ void BL_Shader::ApplyShader()
return; return;
} }
for (unsigned int i = 0; i < mUniforms.size(); i++) {
mUniforms[i]->Apply(this);
}
mDirty = false; mDirty = false;
for (unsigned int i=0; i<mUniforms.size(); i++) {
mDirty |= mUniforms[i]->Apply(this);
}
#endif #endif
} }
@@ -314,64 +324,70 @@ bool BL_Shader::LinkProgram()
return false; return false;
} }
if (vertProg[0] != 0) {
// -- vertex shader ------------------ // -- vertex shader ------------------
tmpVert = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); tmpVert = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
glShaderSourceARB(tmpVert, 1, (const char **)&vertProg, 0); glShaderSourceARB(tmpVert, 1, (const char**)&vertProg, 0);
glCompileShaderARB(tmpVert); glCompileShaderARB(tmpVert);
glGetObjectParameterivARB(tmpVert, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint *)&vertlen); glGetObjectParameterivARB(tmpVert, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*)&vertlen);
// print info if any // print info if any
if (vertlen > 0 && vertlen < MAX_LOG_LEN) { if (vertlen > 0 && vertlen < MAX_LOG_LEN) {
logInf = (char *)MEM_mallocN(vertlen, "vert-log"); logInf = (char*)MEM_mallocN(vertlen, "vert-log");
glGetInfoLogARB(tmpVert, vertlen, (GLsizei *)&char_len, logInf); glGetInfoLogARB(tmpVert, vertlen, (GLsizei*)&char_len, logInf);
if (char_len > 0) { if (char_len > 0) {
spit("---- Vertex Shader Error ----"); spit("---- Vertex Shader Error ----");
spit(logInf); spit(logInf);
} }
MEM_freeN(logInf); MEM_freeN(logInf);
logInf = 0; logInf = 0;
} }
// check for compile errors // check for compile errors
glGetObjectParameterivARB(tmpVert, GL_OBJECT_COMPILE_STATUS_ARB, (GLint *)&vertstatus); glGetObjectParameterivARB(tmpVert, GL_OBJECT_COMPILE_STATUS_ARB, (GLint*)&vertstatus);
if (!vertstatus) { if (!vertstatus) {
spit("---- Vertex shader failed to compile ----"); spit("---- Vertex shader failed to compile ----");
goto programError; goto programError;
} }
}
if (fragProg[0] != 0) {
// -- fragment shader ---------------- // -- fragment shader ----------------
tmpFrag = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); tmpFrag = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
glShaderSourceARB(tmpFrag, 1, (const char **)&fragProg, 0); glShaderSourceARB(tmpFrag, 1, (const char**)&fragProg, 0);
glCompileShaderARB(tmpFrag); glCompileShaderARB(tmpFrag);
glGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint *)&fraglen); glGetObjectParameterivARB(tmpFrag, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*)&fraglen);
if (fraglen > 0 && fraglen < MAX_LOG_LEN) { if (fraglen > 0 && fraglen < MAX_LOG_LEN) {
logInf = (char *)MEM_mallocN(fraglen, "frag-log"); logInf = (char*)MEM_mallocN(fraglen, "frag-log");
glGetInfoLogARB(tmpFrag, fraglen, (GLsizei *)&char_len, logInf); glGetInfoLogARB(tmpFrag, fraglen, (GLsizei*)&char_len, logInf);
if (char_len > 0) { if (char_len > 0) {
spit("---- Fragment Shader Error ----"); spit("---- Fragment Shader Error ----");
spit(logInf); spit(logInf);
} }
MEM_freeN(logInf); MEM_freeN(logInf);
logInf = 0; logInf = 0;
} }
glGetObjectParameterivARB(tmpFrag, GL_OBJECT_COMPILE_STATUS_ARB, (GLint *)&fragstatus); glGetObjectParameterivARB(tmpFrag, GL_OBJECT_COMPILE_STATUS_ARB, (GLint*)&fragstatus);
if (!fragstatus) { if (!fragstatus) {
spit("---- Fragment shader failed to compile ----"); spit("---- Fragment shader failed to compile ----");
goto programError; goto programError;
} }
}
if (!tmpFrag && !tmpVert) {
spit("---- No shader given ----");
goto programError;
}
// -- program ------------------------ // -- program ------------------------
// set compiled vert/frag shader & link // set compiled vert/frag shader & link
tmpProg = glCreateProgramObjectARB(); tmpProg = glCreateProgramObjectARB();
if (tmpVert) {
glAttachObjectARB(tmpProg, tmpVert); glAttachObjectARB(tmpProg, tmpVert);
}
if (tmpFrag) {
glAttachObjectARB(tmpProg, tmpFrag); glAttachObjectARB(tmpProg, tmpFrag);
}
glLinkProgramARB(tmpProg); glLinkProgramARB(tmpProg);
glGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint *)&proglen); glGetObjectParameterivARB(tmpProg, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint *)&proglen);
glGetObjectParameterivARB(tmpProg, GL_OBJECT_LINK_STATUS_ARB, (GLint *)&progstatus); glGetObjectParameterivARB(tmpProg, GL_OBJECT_LINK_STATUS_ARB, (GLint *)&progstatus);
@@ -396,8 +412,12 @@ bool BL_Shader::LinkProgram()
// set // set
mShader = tmpProg; mShader = tmpProg;
if (tmpVert) {
glDeleteObjectARB(tmpVert); glDeleteObjectARB(tmpVert);
}
if (tmpFrag) {
glDeleteObjectARB(tmpFrag); glDeleteObjectARB(tmpFrag);
}
mOk = 1; mOk = 1;
mError = 0; mError = 0;
return true; return true;
@@ -748,6 +768,7 @@ PyMethodDef BL_Shader::Methods[] = {
KX_PYMETHODTABLE(BL_Shader, validate), KX_PYMETHODTABLE(BL_Shader, validate),
// access functions // access functions
KX_PYMETHODTABLE(BL_Shader, isValid), KX_PYMETHODTABLE(BL_Shader, isValid),
KX_PYMETHODTABLE(BL_Shader, setUniformEyef),
KX_PYMETHODTABLE(BL_Shader, setUniform1f), KX_PYMETHODTABLE(BL_Shader, setUniform1f),
KX_PYMETHODTABLE(BL_Shader, setUniform2f), KX_PYMETHODTABLE(BL_Shader, setUniform2f),
KX_PYMETHODTABLE(BL_Shader, setUniform3f), KX_PYMETHODTABLE(BL_Shader, setUniform3f),
@@ -1019,6 +1040,27 @@ KX_PYMETHODDEF_DOC(BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) ")
return NULL; return NULL;
} }
KX_PYMETHODDEF_DOC(BL_Shader, setUniformEyef, "setUniformEyef(name)")
{
if (mError) {
Py_RETURN_NONE;
}
const char *uniform;
float value = 0.0f;
if (PyArg_ParseTuple(args, "s:setUniformEyef", &uniform)) {
int loc = GetUniformLocation(uniform);
if (loc != -1) {
#ifdef SORT_UNIFORMS
SetUniformfv(loc, BL_Uniform::UNI_FLOAT_EYE, &value, sizeof(float));
#else
SetUniform(loc, (int)value);
#endif
}
Py_RETURN_NONE;
}
return NULL;
}
KX_PYMETHODDEF_DOC(BL_Shader, setUniform1i, "setUniform1i(name, ix)") KX_PYMETHODDEF_DOC(BL_Shader, setUniform1i, "setUniform1i(name, ix)")
{ {
if (mError) { if (mError) {

View File

@@ -64,10 +64,11 @@ public:
UNI_FLOAT4, UNI_FLOAT4,
UNI_MAT3, UNI_MAT3,
UNI_MAT4, UNI_MAT4,
UNI_FLOAT_EYE,
UNI_MAX UNI_MAX
}; };
void Apply(class BL_Shader *shader); bool Apply(class BL_Shader *shader);
void SetData(int location, int type, bool transpose = false); void SetData(int location, int type, bool transpose = false);
int GetLocation() { return mLoc; } int GetLocation() { return mLoc; }
void *getData() { return mData; } void *getData() { return mData; }
@@ -226,6 +227,7 @@ public:
KX_PYMETHOD_DOC(BL_Shader, setUniform3i); KX_PYMETHOD_DOC(BL_Shader, setUniform3i);
KX_PYMETHOD_DOC(BL_Shader, setUniform2i); KX_PYMETHOD_DOC(BL_Shader, setUniform2i);
KX_PYMETHOD_DOC(BL_Shader, setUniform1i); KX_PYMETHOD_DOC(BL_Shader, setUniform1i);
KX_PYMETHOD_DOC(BL_Shader, setUniformEyef);
KX_PYMETHOD_DOC(BL_Shader, setUniformfv); KX_PYMETHOD_DOC(BL_Shader, setUniformfv);
KX_PYMETHOD_DOC(BL_Shader, setUniformiv); KX_PYMETHOD_DOC(BL_Shader, setUniformiv);
KX_PYMETHOD_DOC(BL_Shader, setUniformMatrix4); KX_PYMETHOD_DOC(BL_Shader, setUniformMatrix4);