diff options
Diffstat (limited to 'source/gameengine/Ketsji/KX_BlenderMaterial.cpp')
-rw-r--r-- | source/gameengine/Ketsji/KX_BlenderMaterial.cpp | 274 |
1 files changed, 190 insertions, 84 deletions
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index ebf040d3c5d..429a9ea7a65 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -10,6 +10,7 @@ #include <windows.h> #endif // WIN32 #ifdef __APPLE__ +#define GL_GLEXT_LEGACY 1 #include <OpenGL/gl.h> #include <OpenGL/glu.h> #else @@ -22,6 +23,7 @@ #include "KX_Scene.h" #include "KX_Light.h" #include "KX_GameObject.h" +#include "KX_MeshProxy.h" #include "MT_Vector3.h" #include "MT_Vector4.h" @@ -75,7 +77,10 @@ KX_BlenderMaterial::KX_BlenderMaterial( mMaterial(data), mShader(0), mScene(scene), + mUserDefBlend(0), + mModified(0), mPass(0) + { ///RAS_EXT_support._ARB_multitexture == true if were here @@ -101,8 +106,8 @@ KX_BlenderMaterial::KX_BlenderMaterial( // prevent material bleeding for(int i=0; i<mMaterial->num_enabled; i++) { m_multimode += - (mMaterial->flag[i] + - mMaterial->blend_mode[i] + ( mMaterial->flag[i] + + mMaterial->blend_mode[i] ); } m_multimode += mMaterial->IdMode+mMaterial->ras_mode; @@ -132,14 +137,9 @@ void KX_BlenderMaterial::OnConstruction() if(!gTextureDict) gTextureDict = PyDict_New(); */ - #ifdef GL_ARB_shader_objects - if( RAS_EXT_support._ARB_shader_objects ) - mShader = new BL_Shader( mMaterial->num_enabled ); - #endif - int i; for(i=0; i<mMaterial->num_enabled; i++) { - glActiveTextureARB(GL_TEXTURE0_ARB+i); + bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i); #ifdef GL_ARB_texture_cube_map if( mMaterial->mapping[i].mapping & USEENV ) { if(!RAS_EXT_support._ARB_texture_cube_map) { @@ -149,9 +149,6 @@ void KX_BlenderMaterial::OnConstruction() if(!mTextures[i].InitCubeMap( mMaterial->cubemap[i] ) ) spit("unable to initialize image("<<i<<") in "<< mMaterial->matname<< ", image will not be available"); - - if( RAS_EXT_support._ARB_shader_objects ) - mShader->InitializeSampler(SAMP_CUBE, i, 0, mTextures[i]); } else { @@ -160,9 +157,6 @@ void KX_BlenderMaterial::OnConstruction() if( ! mTextures[i].InitFromImage(mMaterial->img[i], (mMaterial->flag[i] &MIPMAP)!=0 )) spit("unable to initialize image("<<i<<") in "<< mMaterial->matname<< ", image will not be available"); - - if( RAS_EXT_support._ARB_shader_objects ) - mShader->InitializeSampler(SAMP_2D, i, 0, mTextures[i]); } #ifdef GL_ARB_texture_cube_map } @@ -170,24 +164,27 @@ void KX_BlenderMaterial::OnConstruction() /*PyDict_SetItemString(gTextureDict, mTextures[i].GetName().Ptr(), PyInt_FromLong(mTextures[i]));*/ } #endif//GL_ARB_multitexture + + mBlendFunc[0] =0; + mBlendFunc[1] =0; } void KX_BlenderMaterial::OnExit() { #ifdef GL_ARB_multitexture - + #ifdef GL_ARB_shader_objects if( RAS_EXT_support._ARB_shader_objects && mShader ) { //note, the shader here is allocated, per unique material //and this function is called per face - glUseProgramObjectARB(0); + bgl::blUseProgramObjectARB(0); delete mShader; mShader = 0; } #endif //GL_ARB_shader_objects for(int i=0; i<mMaterial->num_enabled; i++) { - glActiveTextureARB(GL_TEXTURE0_ARB+i); + bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i); mTextures[i].DeleteTex(); @@ -213,7 +210,7 @@ void KX_BlenderMaterial::OnExit() gTextureDict = 0; }*/ - glActiveTextureARB(GL_TEXTURE0_ARB); + bgl::blActiveTextureARB(GL_TEXTURE0_ARB); #ifdef GL_ARB_texture_cube_map if(RAS_EXT_support._ARB_texture_cube_map) @@ -238,7 +235,7 @@ void KX_BlenderMaterial::DisableTexData() #ifdef GL_ARB_multitexture int i=(MAXTEX>=bgl::max_texture_units?bgl::max_texture_units:MAXTEX)-1; for(; i>=0; i--) { - glActiveTextureARB(GL_TEXTURE0_ARB+i); + bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i); glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); @@ -268,13 +265,13 @@ void KX_BlenderMaterial::setShaderData( bool enable ) int i; if( !enable || !mShader->Ok() ) { // frame cleanup. - glUseProgramObjectARB( 0 ); + bgl::blUseProgramObjectARB( 0 ); DisableTexData(); return; } DisableTexData(); - glUseProgramObjectARB( mShader->GetProg() ); + bgl::blUseProgramObjectARB( mShader->GetProg() ); // for each enabled unit for(i=0; i<mMaterial->num_enabled; i++) { @@ -282,7 +279,7 @@ void KX_BlenderMaterial::setShaderData( bool enable ) const uSampler *samp = mShader->getSampler(i); if( samp->loc == -1 || samp->glTexture == 0 ) continue; - glActiveTextureARB(GL_TEXTURE0_ARB+i); + bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i); #ifdef GL_ARB_texture_cube_map if( mMaterial->mapping[i].mapping &USEENV ) { @@ -297,9 +294,17 @@ void KX_BlenderMaterial::setShaderData( bool enable ) } #endif//GL_ARB_texture_cube_map // use a sampler - glUniform1iARB(samp->loc, i ); + bgl::blUniform1iARB(samp->loc, i ); + } + + if(!mUserDefBlend) { + setDefaultBlending(); + }else + { + glEnable(GL_BLEND); + // tested to be valid enums + glBlendFunc(mBlendFunc[0], mBlendFunc[1]); } - glDisable(GL_BLEND); #endif//GL_ARB_shader_objects #endif//GL_ARB_multitexture @@ -314,7 +319,7 @@ void KX_BlenderMaterial::setTexData( bool enable ) #ifdef GL_ARB_shader_objects if(RAS_EXT_support._ARB_shader_objects) { // switch back to fixed func - glUseProgramObjectARB( 0 ); + bgl::blUseProgramObjectARB( 0 ); } #endif//GL_ARB_shader_objects @@ -336,7 +341,7 @@ void KX_BlenderMaterial::setTexData( bool enable ) // no material connected to the object if( mTextures[0] ) { if( !mTextures[0].Ok() ) return; - glActiveTextureARB(GL_TEXTURE0_ARB); + bgl::blActiveTextureARB(GL_TEXTURE0_ARB); glBindTexture( GL_TEXTURE_2D, mTextures[0] ); glEnable(GL_TEXTURE_2D); setTextureEnvironment( -1 ); // modulate @@ -352,7 +357,7 @@ void KX_BlenderMaterial::setTexData( bool enable ) for(i=0; (i<mMaterial->num_enabled); i++) { if( !mTextures[i].Ok() ) continue; - glActiveTextureARB(GL_TEXTURE0_ARB+i); + bgl::blActiveTextureARB(GL_TEXTURE0_ARB+i); #ifdef GL_ARB_texture_cube_map // use environment maps @@ -388,15 +393,16 @@ void KX_BlenderMaterial::setTexData( bool enable ) #ifdef GL_ARB_texture_cube_map } #endif//GL_ARB_texture_cube_map - - // if either unit has set blending - // and its the last pass - lastblend += setBlending( i ); // dry run - if(lastblend >0 && i==mMaterial->num_enabled-1) - setBlending( i, true ); - else if(lastblend == 0 && i==mMaterial->num_enabled-1) - glDisable(GL_BLEND); } + if(!mUserDefBlend) { + setDefaultBlending(); + }else + { + glEnable(GL_BLEND); + // tested to be valid enums + glBlendFunc(mBlendFunc[0], mBlendFunc[1]); + } + #endif//GL_ARB_multitexture } @@ -548,7 +554,7 @@ KX_BlenderMaterial::Activate( return dopass; } else { - glUseProgramObjectARB( 0 ); + bgl::blUseProgramObjectARB( 0 ); mPass = 0; dopass = false; return dopass; @@ -587,9 +593,8 @@ void KX_BlenderMaterial::setTextureEnvironment( int textureIndex ) glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB ); GLfloat blend_operand = GL_SRC_COLOR; - GLfloat blend_operand_prev = GL_SRC_COLOR; + GLfloat blend_operand_prev = GL_SRC_COLOR; - // all sources here are RGB by default GLenum combiner = GL_COMBINE_RGB_ARB; GLenum source0 = GL_SOURCE0_RGB_ARB; GLenum source1 = GL_SOURCE1_RGB_ARB; @@ -597,6 +602,7 @@ void KX_BlenderMaterial::setTextureEnvironment( int textureIndex ) GLenum op0 = GL_OPERAND0_RGB_ARB; GLenum op1 = GL_OPERAND1_RGB_ARB; GLenum op2 = GL_OPERAND2_RGB_ARB; + GLfloat alphaOp = GL_SRC_ALPHA; // switch to alpha combiners if( (mMaterial->flag[textureIndex] &TEXALPHA) ) { @@ -608,7 +614,6 @@ void KX_BlenderMaterial::setTextureEnvironment( int textureIndex ) op1 = GL_OPERAND1_ALPHA_ARB; op2 = GL_OPERAND2_ALPHA_ARB; blend_operand = GL_SRC_ALPHA; - blend_operand_prev = GL_SRC_ALPHA; // invert if(mMaterial->flag[textureIndex] &TEXNEG) { @@ -618,27 +623,42 @@ void KX_BlenderMaterial::setTextureEnvironment( int textureIndex ) } else { if(mMaterial->flag[textureIndex] &TEXNEG) { - blend_operand_prev = GL_ONE_MINUS_SRC_COLOR; + blend_operand_prev=GL_ONE_MINUS_SRC_COLOR; blend_operand = GL_ONE_MINUS_SRC_COLOR; } } - // on Texture0 GL_PREVIOUS_ARB is the primary color - // on Texture1 GL_PREVIOUS_ARB is Texture0 env + bool using_alpha = false; + + if(mMaterial->flag[textureIndex] &USEALPHA){ + alphaOp = GL_ONE_MINUS_SRC_ALPHA; + using_alpha=true; + } + else if(mMaterial->flag[textureIndex] &USENEGALPHA){ + alphaOp = GL_SRC_ALPHA; + using_alpha = true; + } + switch( mMaterial->blend_mode[textureIndex] ) { case BLEND_MIX: { // ------------------------------ - GLfloat base_col[4]; - base_col[0] = base_col[1] = base_col[2] = 0.f; - base_col[3] = 1.f-mMaterial->color_blend[textureIndex]; - glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,base_col ); + if(!using_alpha) { + GLfloat base_col[4]; + base_col[0] = base_col[1] = base_col[2] = 0.f; + base_col[3] = 1.f-mMaterial->color_blend[textureIndex]; + glTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,base_col ); + } glTexEnvf( GL_TEXTURE_ENV, combiner, GL_INTERPOLATE_ARB); glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB); glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev ); glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); - glTexEnvf( GL_TEXTURE_ENV, source2, GL_CONSTANT_ARB ); - glTexEnvf( GL_TEXTURE_ENV, op2, GL_SRC_ALPHA); + if(!using_alpha) + glTexEnvf( GL_TEXTURE_ENV, source2, GL_CONSTANT_ARB ); + else + glTexEnvf( GL_TEXTURE_ENV, source2, GL_TEXTURE ); + + glTexEnvf( GL_TEXTURE_ENV, op2, alphaOp); }break; case BLEND_MUL: { @@ -647,7 +667,10 @@ void KX_BlenderMaterial::setTextureEnvironment( int textureIndex ) glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB); glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev); glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); - glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); + if(using_alpha) + glTexEnvf( GL_TEXTURE_ENV, op1, alphaOp); + else + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); }break; case BLEND_ADD: { @@ -656,7 +679,10 @@ void KX_BlenderMaterial::setTextureEnvironment( int textureIndex ) glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB ); glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev ); glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); - glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand ); + if(using_alpha) + glTexEnvf( GL_TEXTURE_ENV, op1, alphaOp); + else + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); }break; case BLEND_SUB: { @@ -674,37 +700,16 @@ void KX_BlenderMaterial::setTextureEnvironment( int textureIndex ) glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB ); glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev ); glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); - glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); + if(using_alpha) + glTexEnvf( GL_TEXTURE_ENV, op1, alphaOp); + else + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); } break; } + glTexEnvf( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1.0); #endif //!GL_ARB_texture_env_combine } -bool KX_BlenderMaterial::setBlending( int ind, bool enable) -{ - if(!enable) { - if(mMaterial->flag[ind] &CALCALPHA ) return true; - else if(mMaterial->flag[ind] &USEALPHA ) return true; - return false; - } - else { - // additive - if(mMaterial->flag[ind] &CALCALPHA ) { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - return true; - } - - // use alpha channel - else if(mMaterial->flag[ind] &USEALPHA ) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - return true; - } - } - return false; -} - bool KX_BlenderMaterial::setDefaultBlending() { if( mMaterial->transp &TF_ADD) { @@ -873,6 +878,7 @@ PyMethodDef KX_BlenderMaterial::Methods[] = { KX_PYMETHODTABLE( KX_BlenderMaterial, getShader ), KX_PYMETHODTABLE( KX_BlenderMaterial, getMaterialIndex ), + KX_PYMETHODTABLE( KX_BlenderMaterial, setBlending ), // KX_PYMETHODTABLE( KX_BlenderMaterial, getTexture ), // KX_PYMETHODTABLE( KX_BlenderMaterial, setTexture ), @@ -914,20 +920,78 @@ int KX_BlenderMaterial::_setattr(const STR_String& attr, PyObject *pyvalue) return PyObjectPlus::_setattr(attr, pyvalue); } + KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") { - #ifdef GL_ARB_shader_objects - if(!RAS_EXT_support._ARB_shader_objects) { - PyErr_Format(PyExc_SystemError, "GLSL not supported"); - return NULL; +#ifdef GL_ARB_fragment_shader + if( !RAS_EXT_support._ARB_fragment_shader) { + if(!mModified) + spit("Fragment shaders not supported"); + + mModified = true; + Py_Return; + } +#endif + +#ifdef GL_ARB_vertex_shader + if( !RAS_EXT_support._ARB_vertex_shader) { + if(!mModified) + spit("Vertex shaders not supported"); + + mModified = true; + Py_Return; + } +#endif + +#ifdef GL_ARB_shader_objects + if(!RAS_EXT_support._ARB_shader_objects) { + if(!mModified) + spit("GLSL not supported"); + mModified = true; + Py_Return; } else { - Py_INCREF(mShader); - return mShader; + // returns Py_None on error + // the calling script will need to check + + if(!mShader && !mModified) { + mShader = new BL_Shader(); + for(int i= 0; i<mMaterial->num_enabled; i++) { + if(mMaterial->mapping[i].mapping & USEENV ) + mShader->InitializeSampler(SAMP_CUBE, i, 0, mTextures[i]); + else + mShader->InitializeSampler(SAMP_2D, i, 0, mTextures[i]); + } + mModified = true; + } + + if(mShader && !mShader->GetError()) { + Py_INCREF(mShader); + return mShader; + }else + { + // decref all references to the object + // then delete it! + // We will then go back to fixed functionality + // for this material + if(mShader) { + if(mShader->ob_refcnt > 1) { + Py_DECREF(mShader); + } + else { + delete mShader; + mShader=0; + } + } + } + Py_Return; } - #else + PyErr_Format(PyExc_ValueError, "GLSL Error"); + return NULL; + +#else Py_Return; - #endif//GL_ARB_shader_objects +#endif//GL_ARB_shader_objects } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") @@ -947,3 +1011,45 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setTexture , "setTexture( index, tex)") return NULL; } +static unsigned int GL_array[11] = { + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_SRC_ALPHA_SATURATE +}; + +KX_PYMETHODDEF_DOC( KX_BlenderMaterial, setBlending , "setBlending( GameLogic.src, GameLogic.dest)") +{ + unsigned int b[2]; + if(PyArg_ParseTuple(args, "ii", &b[0], &b[1])) + { + bool value_found[2] = {false, false}; + for(int i=0; i<11; i++) + { + if(b[0] == GL_array[i]) { + value_found[0] = true; + mBlendFunc[0] = b[0]; + } + if(b[1] == GL_array[i]) { + value_found[1] = true; + mBlendFunc[1] = b[1]; + } + if(value_found[0] && value_found[1]) break; + } + if(!value_found[0] || !value_found[1]) { + PyErr_Format(PyExc_ValueError, "invalid enum."); + return NULL; + } + mUserDefBlend = true; + Py_Return; + } + return NULL; +} + |