Archive for July 19th, 2009|Daily archive page

OpenGL ES Texture2D: Power of two

As most of you have figured out, OpenGL ES doesn’t like textures to be non power of two, and I really didn’t want to have to force all of my textures to be powers of two before loading them into my game. This presented me with a problem that had to be solved in-code.

To really understand texture mapping, especially if you’re doing iPhone development or OpenGL ES development in general, it is a good idea to visit Jeff’s blog on the subject located: HERE, and look up chapter 6 on Texture Mapping. I’ll wait, its a great read and should be glanced over at the very least!

Back? OKAY! So the problem is only powers of two can be used in OpenGL ES, so how do we convert our texture to a power of two? There are several ways to do this, but I chose to look at apples version of a texture file and learn from them.

They came up with the following to convert the width and height into a power of two:

//     Adjust the width and height to be a power of two
if( (_width != 1) && (_width & (_width - 1)) ) 
                i = 1;
                while((sizeToFit ? 2 * i : i) < _width)
                        i *= 2;
                _width = i;
        if( (_height != 1) && (_height & (_height - 1)) ) 
                i = 1;
                while((sizeToFit ? 2 * i : i) < _height)
                        i *= 2;
                _height = i;

The first portion of the code will convert the texture to a power of 2. Since the texture will be stretched, and never shrunk, apple had to figure out a way  to shrink the texture if it became larger than the max texture size of 1024. The following code will do just that:

        //      scale down an image greater than the max texture size
        while((_width > kMaxTextureSize) || (_height > kMaxTextureSize)) 
                _width /= 2;
                _height /= 2;
                transform = CGAffineTransformScale(transform, 0.5, 0.5);
                imageSize.x *= 0.5;
                imageSize.y *= 0.5;

the ‘transform’ is nothing more than a CGAffineTransform; in case you were confused with that. So, now that you’ve glanced over the code, you remember in the article where Jeff was talking about S and T coordinates? We’ll take care of those like this:

        _maxS = imageSize.x / (float)_width;
        _maxT = imageSize.y / (float)_height;

This will give us a number between 0 and 1, depending if the texture was re-sized or not. _maxS and _maxT will also be used in our textureCoordinates array for drawing the texture to screen. This should only render the portion of the texture that has any data, and not the padding we added to the texture.

While I am still learning OpenGL, I figured that a lot of people would be interested in the following solution.. especially if you did what I had, and had thrown out the Apple Texture2D file and re-wrote your own. Full source code to the Texture2D, or any other file within the D’Jinn Engine can be found HERE.

Hope this was informative! If anyone has any further information they would like to add, feel free!

Happy Coding Everyone!