ofTexture.loadData() problem

#1

Hi,
I’m now switching from Processing to openFrameworks because of performance-issues, the limited memory allocation in Java, etc…
However, the main thing I want to do is generate big images (~20000px*15000px) and print them later. To do that I want to directly manipulate pixels, that is to draw some more pixels on the screen with each refresh based on some algorithm. Since openFrameworks clears the screen with each refresh, I want to do all my drawing offscreen to a big ofTexture and draw a scaled down version of it on the screen every x’th refresh.
Ok, that’s the theory. My problem is, that I don’t know how to use the ofTexture.loadData() method properly. I tried to use the example from the wiki:

  
unsigned char pixels[200*100];  
for (int i = 0; i < 200*100; i++){  
	pixels[i] = (int)(255 * ofRandomuf());  
}  
myTexture.loadData(pixels, 200, 100, GL_RGB);  
  

I declared the texture in the testApp.h file and I allocated it in the setup method:

  
myTexture.allocate(200,100,GL_RGB);  

But as soon as I try to do myTexture.loadData(pixels,200,100,GL_RGB), my programm crashes.
What’s wrong?

#2

you didn’t pass in enough data!

GL_RGB means it is expecting your array of unsigned char to have a size 3 * that of the number of pixels. You gave it an array that was 1/3 of the size it was expecting. So when it tries to load to texture it runs passed the end of the array and crashes.

For your current code to work try changing GL_RGB to GL_LUMINANCE which is grayscale (1 unsigned char per pixel).

Or if you want to work with RGB pixels then do:

  
unsigned char pixels[200*100 * 3];  
  
//step through 3 pixels at a time  
for (int i = 0; i < 200*100*3; i+= 3){  
    //set red pixel  
    pixels[i] = (int)(255 * ofRandomuf());  
  
    //set green pixel  
    pixels[i+1] = (int)(255 * ofRandomuf());  
  
    //set blue pixel  
    pixels[i+2] = (int)(255 * ofRandomuf());  
}  
  
myTexture.loadData(pixels, 200, 100, GL_RGB);  

#3

Thanks theo. Makes sense…
I didn’t think about that. But then the code example in the api is wrong too.

However, I’ve encountered another problem: Especially when I try to use higher resolutions than 200*100, the texture gets black after a while (sometimes after some minutes, sometimes after the first refresh). No more white-noise (or coloured as in GL_RGB), but just a black rectangle. Even though the pixels array is full of different values.

#4

[quote author=“hrm”]Thanks theo. Makes sense…
I didn’t think about that. But then the code example in the api is wrong too.[/quote]

How is that?
This is the relevant code from the textureExample which is using GL_LUMINANCE to specify 1 byte per pixel.

  
	texGray.allocate(w,h,GL_LUMINANCE);  
  
	grayPixels			= new unsigned char [w*h];  
  
	// gray pixels, set them randomly  
	for (int i = 0; i < w*h; i++){  
		grayPixels[i] = (unsigned char)(ofRandomuf() * 255);  
		  
	}  
	  
	texGray.loadData(grayPixels, w,h, GL_LUMINANCE);   

[quote author=“hrm”]
However, I’ve encountered another problem: Especially when I try to use higher resolutions than 200*100, the texture gets black after a while (sometimes after some minutes, sometimes after the first refresh). No more white-noise (or coloured as in GL_RGB), but just a black rectangle. Even though the pixels array is full of different values.[/quote]

That is strange - can you post the exact code you are using that produces this?

Just to point out there is a limit to the size of a texture in OpenGL - I think the largest is 8192 by 8192 for most NVIDIA / ATI cards. If you want an image of the size you describe then you will have to have it broken up into multiple textures.

This might be helpful as it does something along those lines:
http://forum.openframeworks.cc/t/ofxtilesaver—high-resolution-opengl-screen-grabs/1783/0

Theo

#5

As for the code example with the bug in it: I used the one from http://wiki.openframeworks.cc/index.php?title=OfTexture#loadData which is the one I posted above.

However, here’s the code I’m using now and which works most of the time:

  
  
void testApp::setup(){  
    tex.allocate(800,800,GL_RGBA);  
}  
  
void testApp::draw(){  
    for (int i = 0; i < 800*800*4-3; i+=4){  
        pixels[i]=(int)(25 * ofRandomuf());  
        pixels[i+1]=(int)(105 * ofRandomuf());  
        pixels[i+2]=(int)(15 * ofRandomuf());  
        pixels[i+3]=(int)(125 * ofRandomuf());  
    }  
  
    tex.loadData(pixels,800,800,GL_RGBA);  
    tex.draw(0,0);  
}  

And I added two lines to the testApp.h file:

  
ofTexture tex;  
unsigned char pixels[800*800*4];  

Most of the time, it works, but as I said, sometimes the whole thing turns black and stays so for the rest of the time. (I restarted the computer. It didn’t happen since then…)

But since you mentioned the limits in terms of image-size of ofTexture, I wonder if there’s another way to draw offscreen whithout using ofTexture? Cause I need bigger sizes than 8192 by 8192 without making things too complicated. I have to have a closer look at the code you suggested though.