Saturday, June 12, 2010

GL_TEXTURE_2D

In this part, we continue with a convenient and powerful method for 2D OpenGL, 2D texture.The strength of using OpenGL 2D texture over glDrawPixels is that linear filtering can be selected.Moreover, the task is systematic and not tedious.

I, however, do not know if using RGBA is better in terms of performance or not, but I used it in this example.Thus, we have to modify a way to create a texture image. The A element can be set to 255, as shown below.texImage[nColorBytes*(h*m_nWidth + w) + 3] = (GLubyte) 255;

To initialize 2D texture with linear filtering, the following code can be used to make a texImage an OpenGL texture.void GLTexture2D::initializeGL(){ // Basic initialization glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

To draw a 2D image as a texture, we have to map image coordinates to texture coordinates when we draw GL_QUADS.In the following function, we map the texture created in initializeGL to rectangular coordinates -1.0 to 1.0.

An example project for Eclipse CDT / Qt on Linux is stored at a public folder here.The project file is valid for Eclipse CDT on Linux with Qt integration (Ubuntu 9.04 Juanty), but the main part should be applicable to most C++ environment.

glDrawPixels + Qt (Part 3)

In this part, we will discuss the use of a pixel buffer in OpenGL. A pixel buffer is an advanced feature, which is aimed at increasing screen draw rate.For OpenGL 2.1, this pixel buffer is a part of a standard extension and not in OpenGL core.

To use this extension, things become much more complicated, but can still be explained step by step, as follows.

We need to include <GL/glew.h> before any other OpenGL context. In Qt, we can normally include it in a header file before we include any QGLWidget.For your information, this extension is OpenGL Extension Wrangler Library (GLEW).

Since GLEW is a library, we have to declare its use in a .pro file. Open a .pro file and add a lineLIBS += -lGLEW

Your project can now link to this library properly.

Initialize GLEW before any other OpenGL work. This should be done in the initializeGL method of QGLWidget.Initializing GLEW, however, may fail, especially if we try to initialize it for the second time.Thus, it is recommended to prepare for initialization error, as shown below.GLenum initStatus = glewInit();if (initStatus != GLEW_OK) { cout << "Cannot initialize glew." << endl; exit(1);} else cout << "glew is successfully initialized." << endl;

Bind data to a buffer. We need to provide a non-local GLuint to be employed as a buffer ID. This may be a class-member or global variable.Assume that we declare the ID variable as a class member by

GLuint pixelBuffer;

Next, bind the buffer to it. Note that chkImage contains pixel data and must be already filled.These patch of code is still in initializeGL.

So, what if we have several buffers? In that case, we have to prepare more buffer-ID variables, bind them, and populate them. At the painting time, we specify our target buffer. For concreateness, see the code below.

An example Eclipse CDT / Qt project is stored at a public folder here.The project file is valid for Eclipse CDT on Linux with Qt integration (Ubuntu 9.04 Juanty), but the main part should be applicable to most C++ environment.

glDrawPixels + Qt (Part 2)

In this part, we are going to use Qt to load an image from a file and display it with QGLWidget by using glDrawPixels.The process is generally the same, except the order of function calls and the use of Qt to load an image file.

The function makeImage() is called early because we want to know image dimensions and give a correct size hint to a QGLWidget.initializeGL is, therefore, leaner.void GLImage2_1::initializeGL(){ // Set coordinate system glOrtho(0, m_nWidth, 0, m_nHeight, 0, 1);

We have no need to explicitly supply the image file type to its load function. Qt first relies on file extension (.jpg, .png, for example). If it fails or there is no file extension, Qt will make a guess based on file header.

Notice the use of int nImgH = m_nHeight - h - 1; This is essential because the image coordinate system in OpenGL is different from most computer imaging systems, including Qt. In Qt the origin is at top left and the y-axis points downward, while in OpenGL, the origin is at bottom left and the y-axis points upward. Since the x-axes in Qt and OpenGL are the same, there is no need to convert x-coordinates.

========================================

An example Eclipse CDT / Qt project is stored at a public folder here. The project file is valid for Eclipse CDT on Linux with Qt integration (Ubuntu 9.04 Juanty), but the main part should be applicable to most C++ environment.

glDrawPixels + Qt (Part 1)

This is an article following GL_POINTS + Qt. As mentioned earlier, we can use glDrawPixels with glPixelZoom to deal with 2D graphics.Although it appears to be more complicated than GL_POINTS, glDrawPixels is still another simple method.

The strength of glDrawPixels is its ability to scale an image in a way most people expect. For example, a pixel in the original scale may occupy more than one pixel in a window, if the window is scaled up.We can also increase draw rate by using buffer, but Part 1 will not cover that topic.

Now, let's see how to draw an image by using glDrawPixels and glPixelZoom. Recall that the coordinate system of OpenGL may be different from most imaging systems. OpenGL set the origin at the bottom left by default.

The major difference between GL_POINTS and glDrawPixels is that GL_POINTS is based on a call list, while glDrawPixels is based on an array.This array is a flatten 3D or 4D array. Namely, RGB(A) data is kept together in a 1D array. We have to tell OpenGL a color model we want to use.

Assume that we want to use the RGB color model and the image is of size 128x128 pixels. Therefore, we have to create a 1D array of size 128x128x3. RGB values of one pixels are packed at contiguous array cells, as shown below./// Build a checker board, each grid cell is of size 16 x 16 pixels./// 0x10 is a base-16 number equal to 16.void GLImage::makeImage() { chkImage = new GLubyte[m_nHeight * m_nWidth * 3];

Notice the use of glShadeModel(GL_FLAT). glPixelStorei is employed to specify the way we store color data. The parameter 1 indicates that it is 1-btye alignment. Basically, there is no restriction of the beginning position of each row with this parameter. If it is 2, each row must start on even-numbered byte.

========================================

An example Eclipse CDT / Qt project is stored at a public folder here.The project file is valid for Eclipse CDT on Linux with Qt integration (Ubuntu 9.04 Juanty), but the main part should be applicable to most C++ environment.