Hello,
For introduction, my problem concerns texture-based 2-D image visualization. I know the subject pops out every once and while and I’ve googled it all. No real answer though and granted, PBO’s ain’t the solution here.
My problem is image load / reload speed which gets unacceptable slow. I cannot even change dynamic range at interactive speeds, not to mention hue, saturation or contrast. How does Photoshop implement its visualization? Any wild guesses? With hardware rendering turned on, it looks / behaves (seemless zoom, panning etc.) similar to my implementation. That is, after the image has been loaded!
Real world example: ~15Mpix RGB-image takes .899 seconds to reload.
Here’s my code samples: load is used for the first time, reload afterwards, e.g. in case of image modification (in tests, I’ve used null-modification, so the time is pretty much spent entirely on gl-functions). The image is tiled of (2^N)x(2^N) blocks. One texture is out of question to support large images, and to my experience, 256 seems the optimal texture size. I’ve tested RGBA / BGRA_EXT and several other combinations. LUMINANCE_ALPHA, in case of black&white images is of course faster, but this cannot be bandwidth issue, since 62MB << 4GB for PCIe x16. One more thing, I cannot really see a difference between load and reload. Rendering is done by Windows-WM_PAINT, so not affecting this problem. The copying into buffer is mandatory anyway to support arbitrary dynamic ranges in floating point images.
Anyone? Would ya?
#define MY_TEXSIZE 256
class TextureObject;
void Load(){
/*std::list<TextureObject> m_textures;*/
DWORD *buffer = new DWORD[MY_TEXSIZE * MY_TEXSIZE];
for ( /* loop over tiled image */ ){
/* compute tile and texture coordinates in texture object */
/* copy part of RGB (BGR) image to contiquous RGBA (BGRA) buffer */
DWORD *d_ptr = (DWORD*)buffer;
BYTE *im_ptr = (BYTE*)image->bits /* + location to current tile */;
for(y=0;y<MY_TEXSIZE;++y){
for(x=0;x<MY_TEXSIZE;++x){
*(d_ptr++) = (*((DWORD*)im_ptr) & 0xffffff) | shiftedAlpha;
im_ptr += 3;
}
im_ptr += offset;
}
glGenTextures( 1, &(tex.m_texname) );
glBindTexture( GL_TEXTURE_2D, tex.m_texname );
m_textures.push_back( tex );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, MY_TEXSIZE, MY_TEXSIZE,
0, GL_BGRA_EXT,GL_UNSIGNED_BYTE, buffer );
}
}
void Reload(){
std::list<TextureObject>::const_iterator it;
for ( /* loop over tiled image */ ){
/* make your changes to image and load it into buffer */
glBindTexture( GL_TEXTURE_2D, (*it).m_texname );
glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, MY_TEXSIZE, MY_TEXSIZE,
GL_BGRA_EXT, GL_UNSIGNED_BYTE, buffer );
++it;
}
}