From e4790aef46f7ca0b4ab01c34f043be9e7b1fa7f1 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Mon, 13 Feb 2006 05:45:32 +0000 Subject: Improved OpenGL Shader Language support for game engine. The python interface is much simplified. Drawback is that scripts need to be updated next release. Testfiles: http://www.continuousphysics.com/ftp/pub/test/index.php?dir=blender/&file=demos-2.42.zip patch by Charlie Carley (snailrose @ elysiun.com) --- source/gameengine/Ketsji/BL_Texture.cpp | 402 ++++++++++++++++++++++++++------ 1 file changed, 325 insertions(+), 77 deletions(-) (limited to 'source/gameengine/Ketsji/BL_Texture.cpp') diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index 7cabb65a3ba..4ff31b885ba 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -23,19 +23,22 @@ #include "BKE_image.h" #include "BLI_blenlib.h" -#include "RAS_GLExtensionManager.h" +#include "RAS_OpenGLRasterizer/RAS_GLExtensionManager.h" +#include "RAS_OpenGLRasterizer/ARB_multitexture.h" +#include "RAS_ICanvas.h" +#include "RAS_Rect.h" + +#include "KX_GameObject.h" + using namespace bgl; #define spit(x) std::cout << x << std::endl; #include "MEM_guardedalloc.h" - - extern "C" { // envmaps #include "IMB_imbuf.h" - void my_envmap_split_ima(EnvMap *env); void my_free_envmapdata(EnvMap *env); } @@ -50,15 +53,14 @@ static int smaller_pow2(int num) { return num; } - - BL_Texture::BL_Texture() : mTexture(0), mError(0), mOk(0), mNeedsDeleted(0), mType(0), - mName("") + mName(""), + mUnit(0) { // -- } @@ -71,14 +73,14 @@ BL_Texture::~BL_Texture() void BL_Texture::DeleteTex() { if( mNeedsDeleted ) { - glDeleteTextures(1, (GLuint*)&(*mTexture)); + glDeleteTextures(1, (GLuint*)&mTexture); mNeedsDeleted = 0; mOk = 0; } } -bool BL_Texture::InitFromImage( Image *img, bool mipmap) +bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) { if(!img || img->ok==0 ) { mError = true; @@ -94,17 +96,20 @@ bool BL_Texture::InitFromImage( Image *img, bool mipmap) return mOk; } } - mTexture = &img->bindcode; + mTexture = img->bindcode; + mName = img->id.name; - mType = BL_TEX2D; - + mType = GL_TEXTURE_2D; + mUnit = unit; + // smoke em if we got em - if (*mTexture != 0) { - glBindTexture(GL_TEXTURE_2D, *mTexture ); + if (mTexture != 0) { + glBindTexture(GL_TEXTURE_2D, mTexture ); Validate(); return mOk; } - glGenTextures(1, (GLuint*)mTexture); + mNeedsDeleted = 1; + glGenTextures(1, (GLuint*)&mTexture); InitGLTex(img->ibuf->rect, img->ibuf->x, img->ibuf->y, mipmap); Validate(); return mOk; @@ -117,7 +122,7 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) return; } - glBindTexture(GL_TEXTURE_2D, *mTexture ); + glBindTexture(GL_TEXTURE_2D, mTexture ); if( mipmap ) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -141,7 +146,7 @@ void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int)); gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels); - glBindTexture(GL_TEXTURE_2D, *mTexture ); + glBindTexture(GL_TEXTURE_2D, mTexture ); if( mipmap ) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); @@ -158,7 +163,7 @@ void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) } -bool BL_Texture::InitCubeMap( EnvMap *cubemap ) +bool BL_Texture::InitCubeMap(int unit, EnvMap *cubemap ) { #ifdef GL_ARB_texture_cube_map if(!RAS_EXT_support._ARB_texture_cube_map) { @@ -186,13 +191,14 @@ bool BL_Texture::InitCubeMap( EnvMap *cubemap ) EnvMap *CubeMap = cubemap; mNeedsDeleted = 1; - mBlankTexture = 0; - mType = BL_TEXCUBE; - mTexture = &mBlankTexture; + mType = GL_TEXTURE_CUBE_MAP_ARB; + mTexture = 0; mName = CubeMap->ima->id.name; + mUnit = unit; - glGenTextures(1, (GLuint*)(mTexture)); - glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, *mTexture ); + + glGenTextures(1, (GLuint*)&mTexture); + glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mTexture ); bool needs_split = false; if(!CubeMap->cube[0]) needs_split = true; @@ -202,72 +208,49 @@ bool BL_Texture::InitCubeMap( EnvMap *cubemap ) my_envmap_split_ima(CubeMap); } - int x = cubemap->ima->ibuf->x; - int y = cubemap->ima->ibuf->y; - unsigned int *data= (unsigned int *)malloc(x*y*sizeof(unsigned int)); + int x = CubeMap->ima->ibuf->x; + int y = CubeMap->ima->ibuf->y; // ----------------------------------- x = CubeMap->cube[0]->ibuf->x; y = CubeMap->cube[0]->ibuf->y; // check the first image, and assume the rest - if (!is_pow2(x) || !is_pow2(y)) - { + if (!is_pow2(x) || !is_pow2(y)) { spit("invalid envmap size please render with CubeRes @ power of two"); - free(data); - data = 0; + my_free_envmapdata(CubeMap); mError = true; mOk = false; return mOk; } - memcpy(data, CubeMap->cube[0]->ibuf->rect, (x*y*sizeof(unsigned int))); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - - // ----------------------------------- - x = CubeMap->cube[1]->ibuf->x; - y = CubeMap->cube[1]->ibuf->y; - memcpy(data, CubeMap->cube[1]->ibuf->rect, (x*y*sizeof(unsigned int))); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - - // ----------------------------------- - x = CubeMap->cube[2]->ibuf->x; - y = CubeMap->cube[2]->ibuf->y; - memcpy(data, CubeMap->cube[2]->ibuf->rect, (x*y*sizeof(unsigned int))); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - - // ----------------------------------- - x = CubeMap->cube[3]->ibuf->x; - y = CubeMap->cube[3]->ibuf->y; - memcpy(data, CubeMap->cube[3]->ibuf->rect, (x*y*sizeof(unsigned int))); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - - // ----------------------------------- - x = CubeMap->cube[4]->ibuf->x; - y = CubeMap->cube[4]->ibuf->y; - memcpy(data, CubeMap->cube[4]->ibuf->rect, (x*y*sizeof(unsigned int))); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - - // ----------------------------------- - x = CubeMap->cube[5]->ibuf->x; - y = CubeMap->cube[5]->ibuf->y; - memcpy(data, CubeMap->cube[5]->ibuf->rect, (x*y*sizeof(unsigned int))); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + /* + */ + +#define SetCubeMapFace(face, num) \ + glTexImage2D(face, 0,GL_RGBA, \ + CubeMap->cube[num]->ibuf->x, \ + CubeMap->cube[num]->ibuf->y, \ + 0, GL_RGBA, GL_UNSIGNED_BYTE, \ + CubeMap->cube[num]->ibuf->rect) + + SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 5); + SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 3); + SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0); + SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 1); + SetCubeMapFace(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 2); + SetCubeMapFace(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 4); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri( GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT ); - - if(data) { - free(data); - data = 0; - } + if(needs_split) { - // okay we allocated, swap back to orig and free used cubemap->ima = CubeMap->ima; my_free_envmapdata(CubeMap); } + mOk = IsValid(); return mOk; @@ -289,7 +272,7 @@ STR_String BL_Texture::GetName() const bool BL_Texture::IsValid() { - return (mTexture && *mTexture!= 0)?glIsTexture(*mTexture)!=0:false; + return (mTexture!= 0)?glIsTexture(mTexture)!=0:false; } @@ -301,7 +284,7 @@ void BL_Texture::Validate() bool BL_Texture::Ok() { - return ( mTexture?((!mError || mOk ) && *mTexture!= 0):0 ); + return (mTexture!= 0); } @@ -310,15 +293,282 @@ unsigned int BL_Texture::GetTextureType() const return mType; } +int BL_Texture::GetMaxUnits() +{ + GLint unit=0; +#ifdef GL_ARB_multitexture + if(RAS_EXT_support._ARB_multitexture) { + glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit); + return (MAXTEX>=unit?unit:MAXTEX); + } +#endif + return 0; +} + +void BL_Texture::ActivateFirst() +{ +#ifdef GL_ARB_multitexture + if(RAS_EXT_support._ARB_multitexture) + bgl::blActiveTextureARB(GL_TEXTURE0_ARB); +#endif +} + +void BL_Texture::ActivateUnit(int unit) +{ +#ifdef GL_ARB_multitexture + if(RAS_EXT_support._ARB_multitexture) { + if(unit <= MAXTEX) + bgl::blActiveTextureARB(GL_TEXTURE0_ARB+unit); + } +#endif +} + -BL_Texture::operator const unsigned int () const +void BL_Texture::DisableUnit() { - return mTexture? *mTexture:0; +#ifdef GL_ARB_multitexture + if(RAS_EXT_support._ARB_multitexture) + bgl::blActiveTextureARB(GL_TEXTURE0_ARB+mUnit); +#endif + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + +#ifdef GL_ARB_texture_cube_map + if(RAS_EXT_support._ARB_texture_cube_map) + glDisable(GL_TEXTURE_CUBE_MAP_ARB); +#endif + glDisable(GL_TEXTURE_2D); + glDisable(GL_TEXTURE_GEN_S); + glDisable(GL_TEXTURE_GEN_T); + glDisable(GL_TEXTURE_GEN_R); + glDisable(GL_TEXTURE_GEN_Q); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); } -bool BL_Texture::SetGLTex(unsigned int tex) + +void BL_Texture::DisableAllTextures() { - return false; +#ifdef GL_ARB_multitexture + glDisable(GL_BLEND); + for(int i=0; iflag[mUnit] &TEXALPHA ) { + combiner = GL_COMBINE_ALPHA_ARB; + source0 = GL_SOURCE0_ALPHA_ARB; + source1 = GL_SOURCE1_ALPHA_ARB; + source2 = GL_SOURCE2_ALPHA_ARB; + op0 = GL_OPERAND0_ALPHA_ARB; + op1 = GL_OPERAND1_ALPHA_ARB; + op2 = GL_OPERAND2_ALPHA_ARB; + blend_operand = GL_SRC_ALPHA; + blend_operand_prev = GL_SRC_ALPHA; + // invert + if(mat->flag[mUnit] &TEXNEG) { + blend_operand_prev = GL_ONE_MINUS_SRC_ALPHA; + blend_operand = GL_ONE_MINUS_SRC_ALPHA; + } + } + else { + if(mat->flag[mUnit] &TEXNEG) { + blend_operand_prev=GL_ONE_MINUS_SRC_COLOR; + blend_operand = GL_ONE_MINUS_SRC_COLOR; + } + } + bool using_alpha = false; + + if(mat->flag[mUnit] &USEALPHA){ + alphaOp = GL_ONE_MINUS_SRC_ALPHA; + using_alpha=true; + } + else if(mat->flag[mUnit] &USENEGALPHA){ + alphaOp = GL_SRC_ALPHA; + using_alpha = true; + } + + switch( mat->blend_mode[mUnit] ) { + case BLEND_MIX: + { + // ------------------------------ + if(!using_alpha) { + GLfloat base_col[4]; + base_col[0] = base_col[1] = base_col[2] = 0.f; + base_col[3] = 1.f-mat->color_blend[mUnit]; + 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); + 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: + { + // ------------------------------ + glTexEnvf( GL_TEXTURE_ENV, combiner, GL_MODULATE); + glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB); + glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev); + glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); + if(using_alpha) + glTexEnvf( GL_TEXTURE_ENV, op1, alphaOp); + else + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); + }break; + case BLEND_ADD: + { + // ------------------------------ + glTexEnvf( GL_TEXTURE_ENV, combiner, GL_ADD_SIGNED_ARB); + glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB ); + glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev ); + glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); + if(using_alpha) + glTexEnvf( GL_TEXTURE_ENV, op1, alphaOp); + else + glTexEnvf( GL_TEXTURE_ENV, op1, blend_operand); + }break; + case BLEND_SUB: + { + // ------------------------------ + glTexEnvf( GL_TEXTURE_ENV, combiner, GL_SUBTRACT_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); + }break; + case BLEND_SCR: + { + // ------------------------------ + glTexEnvf( GL_TEXTURE_ENV, combiner, GL_ADD); + glTexEnvf( GL_TEXTURE_ENV, source0, GL_PREVIOUS_ARB ); + glTexEnvf( GL_TEXTURE_ENV, op0, blend_operand_prev ); + glTexEnvf( GL_TEXTURE_ENV, source1, GL_TEXTURE ); + 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 +} + +int BL_Texture::GetPow2(int n) +{ + if(!is_pow2(n)) + n = smaller_pow2(n); + + return n; } extern "C" { @@ -384,7 +634,5 @@ void my_free_envmapdata(EnvMap *env) } -} - -unsigned int BL_Texture::mBlankTexture = 0; +} // extern C -- cgit v1.2.3