Using ofTexture for memory optimization

There are two types of memory in a computer – Random Access Memory (RAM), which is used by the Central Processing Unit (CPU), and video memory, which is used by the video card; that is, the Graphics Processing Unit (GPU). RAM is intended for making calculations and video memory is used for drawing something on the screen.

Note

A typical GPU contains hundreds of computing cores and its number is increasing every year. This is the reason why new GPUs can have more computing power than CPUs, which has just 1 to 16 cores. Today, almost all computations can be made on the GPU using technologies such as shaders, OpenCL or NVIDIA CUDA. Hence the CPU is no longer the most important unit in a computer. For example, the visual development platform Derivative Touch Designer (for Windows only) does its processing almost entirely on the GPU.

Though programming in GPUs is a very powerful tool, it's a little tricky when compared to CPU programming. Also, debugging GPUs is not so convenient yet. So, in this book, we still mainly consider programming in CPU and only touch GPU programming when talking about shaders in Chapter 8, Using Shaders.

The architecture of a computer assumes all images, vector graphics, and 3D objects that will be depicted on the screen should be loaded at first into the video memory. Images in the video memory are called textures. By default, openFrameworks's class ofImage holds two same images. These are the pixel array in RAM that can be accessed by image.getPixels() and its clone, the texture in the video memory that can be accessed by image.getTextureReference().

So, when you change the pixel array of image, you need to call image.update() in order to apply the changes to the corresponding texture.

You may ask why is such a double representation needed? Yes, indeed, it is possible to discard the texture (using the image.setUseTexture( false ) function) and to render the pixel array directly on the screen. But this operation needs to load the pixel array into the video memory anyway, which is a fast but nevertheless time-consuming operation. So, if we did not change the image or wish to draw it several times on the screen, it is better to have a texture for it.

You can discard a pixel array too. Pixel arrays are just tools for writing images to disks and a convenient way of changing it using CPUs. So, if you do not want to change your image, it is good idea to use only textures, without having pixel arrays in the RAM. To do so, use ofTexture instead of ofImage. In case you are using ofTexture, your image will lie in the video memory only and will not occupy any RAM. So you obtain memory optimization, which is crucial for large projects.

The usage of a texture in the code is much like the use of an instance of ofImage. The following are the functions used for working with textures:

  • ofLoadImage( texture, fileName ) – loads texture from an image file, fileName
  • ofSaveImage( texture, fileName ) – saves texture to image file, fileName
  • texture.draw( x, y ) or texture.draw( x, y, w, h ) – draws texture
  • texture.loadData( data, w, h, format ) – creates texture from the pixel array data, where format is GL_RGBA, GL_RGB, or GL_LUMINANCE for 4, 3, or 1 channel images respectively.
  • texture.getWidth() and texture.getHeight() are used for getting texture dimensions.

Here is example of using ofTexture for drawing images:

#include "testApp.h"

ofTexture  texture;    //Declare texture

void testApp::setup(){
  //Load texture from file
  ofLoadImage( texture, "sunflower.png" );
}

void testApp::update(){
}

void testApp::draw(){
  ofBackground(255, 255, 255);     //Set background color
  ofSetColor( 255, 255, 255 );
  texture.draw( 0, 0 );            //Draw texture
}

We had discussed the basics of textures and now will see how to use it for image warping and its application for video mapping.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset