Rendering to non-power-of-two texture on iPhone

While OpenGL ES 1.1 does not support non-power-of-two textures, newer iOS device models have the extension GL_APPLE_texture_2D_limited_npot, which states:

Conventional OpenGL ES 1.X texturing
is limited to images with power-of-two
(POT) dimensions.
APPLE_texture_2D_limited_npot
extension relaxes these size
restrictions for 2D textures. The
restrictions remain in place for cube
map and 3D textures, if supported.

There is no additional procedural or
enumerant API introduced by this
extension except that an
implementation which exports the
extension string will allow an
application to pass in 2D texture
dimensions that may or may not be a
power of two.

In the absence of OES_texture_npot,
which lifts these restrictions,
neither mipmapping nor wrap modes
other than CLAMP_TO_EDGE are supported
in conjunction with NPOT 2D textures.
A NPOT 2D texture with a wrap mode
that is not CLAMP_TO_EDGE or a
minfilter that is not NEAREST or
LINEAR is considered incomplete. If
such a texture is bound to a texture
unit, it is as if texture mapping
were disabled for that texture unit.

You can use the following code to determine if this extension is supported on your device (drawn from Philip Rideout’s excellent iPhone 3D Programming book):

const char* extensions = (char*) glGetString(GL_EXTENSIONS); 
bool npot = strstr(extensions, "GL_APPLE_texture_2D_limited_npot") != 0;

On these devices, you should then be able to use non-power-of-two textures as long as you set the proper texture wrapping:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Unfortunately, this example application that I have which renders to a non-power-of-two texture uses OpenGL ES 2.0, so I’m not sure that will help you in this case.

Leave a Comment