void ofxTexture3d::loadData(void * data, int w, int h, int d, int xOffset, int yOffset, int zOffset, int glFormat) { if(glFormat!=texData.glType) { ofLogError() << "ofxTexture3d::loadData() failed to upload format " << ofGetGlInternalFormatName(glFormat) << " data to " << ofGetGlInternalFormatName(texData.glType) << " texture" <<endl; return; } if(w > texData.tex_w || h > texData.tex_h || d > texData.tex_d) { ofLogError() << "ofxTexture3d::loadData() failed to upload " << w << "x" << h << "x" << d << " data to " << texData.tex_w << "x" << texData.tex_h << "x" << texData.tex_d << " texture"; return; } ofSetPixelStoreiAlignment(GL_UNPACK_ALIGNMENT,w,1,ofGetNumChannelsFromGLFormat(glFormat)); glEnable(texData.textureTarget); glBindTexture(texData.textureTarget, (GLuint) texData.textureID); glTexSubImage3D(texData.textureTarget, 0, xOffset, yOffset, zOffset, w, h, d, texData.glType, texData.pixelType, data); glDisable(texData.textureTarget); }
//---------------------------------------------------------- void ofTexture::loadData(void * data, int w, int h, int glInternalFormat){ // can we allow for uploads bigger then texture and // just take as much as the texture can? // // ie: // int uploadW = MIN(w, tex_w); // int uploadH = MIN(h, tex_h); // but with a "step" size of w? // check "glTexSubImage2D" if(!ofCheckGLTypesEqual(glInternalFormat,texData.glTypeInternal)) { ofLogError() << "ofTexture::loadData() failed to upload internalFormat " << ofGetGlInternalFormatName(glInternalFormat) << " data to " << ofGetGlInternalFormatName(texData.glTypeInternal) << " texture"; return; } if(w > texData.tex_w || h > texData.tex_h) { ofLogError() << "ofTexture::loadData() failed to upload " << w << "x" << h << " data to " << texData.tex_w << "x" << texData.tex_h << " texture"; return; } // update our size with the new dimensions texData.width = w; texData.height = h; // compute new tex co-ords based on the ratio of data's w, h to texture w,h; #ifndef TARGET_OPENGLES if (texData.textureTarget == GL_TEXTURE_RECTANGLE_ARB){ texData.tex_t = w; texData.tex_u = h; } else #endif { texData.tex_t = (float)(w) / (float)texData.tex_w; texData.tex_u = (float)(h) / (float)texData.tex_h; } // ok this is an ultra annoying bug : // opengl texels and linear filtering - // when we have a sub-image, and we scale it // we can clamp the border pixels to the border, // but the borders of the sub image get mixed with // neighboring pixels... // grr... // // the best solution would be to pad out the image // being uploaded with 2 pixels on all sides, and // recompute tex_t coordinates.. // another option is a gl_arb non pow 2 textures... // the current hack is to alter the tex_t, tex_u calcs, but // that makes the image slightly off... // this is currently being done in draw... // // we need a good solution for this.. // // http://www.opengl.org/discussion_boards/ubb/ultimatebb.php?ubb=get_topic;f=3;t=014770#000001 // http://www.opengl.org/discussion_boards/ubb/ultimatebb.php?ubb=get_topic;f=3;t=014770#000001 //------------------------ likely, we are uploading continuous data GLint prevAlignment; glGetIntegerv(GL_UNPACK_ALIGNMENT, &prevAlignment); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //Sosolimited: texture compression if (texData.compressionType == OF_COMPRESS_NONE) { //STANDARD openFrameworks: no compression //update the texture image: glEnable(texData.textureTarget); glBindTexture(texData.textureTarget, (GLuint) texData.textureID); glTexSubImage2D(texData.textureTarget, 0, 0, 0, w, h, texData.glType, texData.pixelType, data); glDisable(texData.textureTarget); } else { //SOSOLIMITED: setup mipmaps and use compression //TODO: activate at least mimaps for OPENGL_ES //need proper tex_u and tex_t positions, with mipmaps they are the nearest power of 2 #ifndef TARGET_OPENGLES if (texData.textureTarget == GL_TEXTURE_RECTANGLE_ARB){ //need to find closest powers of two int last_h = ofNextPow2(texData.height)>>1; int next_h = ofNextPow2(texData.height); if ((texData.height - last_h) < (next_h - texData.height)) texData.tex_u = last_h; else texData.tex_u = next_h; int last_w = ofNextPow2(texData.width)>>1; int next_w = ofNextPow2(texData.width); if ((texData.width - last_w) < (next_w - texData.width)) texData.tex_t = last_w; else texData.tex_t = next_w; //printf("ofTexture::loadData w:%.1f, h:%.1f, tex_t:%.1f, tex_u:%.1f \n", texData.width,texData.height,texData.tex_t,texData.tex_u); } #endif glEnable(texData.textureTarget); glBindTexture(texData.textureTarget, (GLuint)texData.textureID); glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); #ifndef TARGET_OPENGLES glTexParameteri(texData.textureTarget, GL_GENERATE_MIPMAP_SGIS, true); #endif glTexParameteri( texData.textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri( texData.textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri( texData.textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri( texData.textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2); #ifndef TARGET_OPENGLES //using sRGB compression if (texData.compressionType == OF_COMPRESS_SRGB) { if(texData.glType == GL_RGBA) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_SRGB_ALPHA, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_RGB) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_SRGB_ALPHA, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_LUMINANCE_ALPHA) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_SRGB_ALPHA, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_LUMINANCE) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_SRGB_ALPHA, w, h, texData.glType, texData.pixelType, data); } //using ARB compression: default else { if(texData.glType == GL_RGBA) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_RGBA_ARB, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_RGB) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_RGB_ARB, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_LUMINANCE_ALPHA) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_LUMINANCE_ALPHA_ARB, w, h, texData.glType, texData.pixelType, data); else if(texData.glType == GL_LUMINANCE) gluBuild2DMipmaps(texData.textureTarget, GL_COMPRESSED_LUMINANCE_ARB, w, h, texData.glType, texData.pixelType, data); } #endif glDisable(texData.textureTarget); }