OpenGL ES Loading Textures
I have a major problem loading png textures on my OpenGL ES code. I need some help doing so, because this will drive me nuts.
here is the code with which I am loading textures:
However, this code works with some png files, but not with others! I am enclosing my entire project for you to see. In this project, I have created a 2D mesh, and I am displaying a texture with it.
I am using Cocos2D for the setup, but this has nothing to do with the rest of the OpenGL code, as I am doing all of the drawing in OpenGL ES. In the project, if you try running it with "romo.png", "bluetex.png", "combinedtextures.png" as the active image, the image will be displayed correctly. Otherwise, it will not be displayed. I have made tests with the Texture2D classes to no effect.
Please, download the project (...which is for your convenience. No essential or copyrighted code is written in there) and tackle with the images to see what's happening.
The project is The project is here
Can anyone help me, or at least point me somewhere where I can see how to load PNG files correctly? This is driving me nuts!
here is the code with which I am loading textures:
Code:
- (void)loadTexture:(NSString *)name intoLocation:(GLuint)location {
CGImageRef textureImage = [UIImage imageNamed:name].CGImage;
if (textureImage == nil) {
NSLog(@"Failed to load texture image");
return;
}
NSInteger texWidth = CGImageGetWidth(textureImage);
NSInteger texHeight = CGImageGetHeight(textureImage);
GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight * 4);
CGContextRef textureContext = CGBitmapContextCreate(textureData,
texWidth, texHeight,
8, texWidth * 4,
CGImageGetColorSpace(textureImage),
kCGImageAlphaPremultipliedLast);
// Rotate the image
CGContextTranslateCTM(textureContext, 0, texHeight);
CGContextScaleCTM(textureContext, 1.0, -1.0);
CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight), textureImage);
CGContextRelease(textureContext);
glBindTexture(GL_TEXTURE_2D, location);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
free(textureData);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}However, this code works with some png files, but not with others! I am enclosing my entire project for you to see. In this project, I have created a 2D mesh, and I am displaying a texture with it.
I am using Cocos2D for the setup, but this has nothing to do with the rest of the OpenGL code, as I am doing all of the drawing in OpenGL ES. In the project, if you try running it with "romo.png", "bluetex.png", "combinedtextures.png" as the active image, the image will be displayed correctly. Otherwise, it will not be displayed. I have made tests with the Texture2D classes to no effect.
Please, download the project (...which is for your convenience. No essential or copyrighted code is written in there) and tackle with the images to see what's happening.
The project is The project is here
Can anyone help me, or at least point me somewhere where I can see how to load PNG files correctly? This is driving me nuts!
Add one line of debug code:
You'll see that the 256x256 textures work, and the others like 480x320 produce GL_INVALID_VALUE.
It's because the hardware only supports power-of-two textures.
Code:
...
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
printf("Got error %04x for TexImage %d x %d\n", glGetError(), texWidth, texHeight);
...You'll see that the 256x256 textures work, and the others like 480x320 produce GL_INVALID_VALUE.
It's because the hardware only supports power-of-two textures.
Yes, you are indeed right. I had forgotten that very important detail, and that cost me frustration, and your time, sorry. Thanks a lot for taking the time to look at it.
Can you show me how can I bypass that limitation?
I would really like to be able to load 2D textures as background images that are 480x360 in size... (the size of the iPhone screen)
Can you show me how can I bypass that limitation?
I would really like to be able to load 2D textures as background images that are 480x360 in size... (the size of the iPhone screen)
You have three options:
1) Resize the image to a power of two. If you resize down, you lose quality. Resizing up uses more memory.
2) Keep the image the same size, but put it inside of a larger power-of-two texture. You can put other things in the extra padding space (i.e. make a texture atlas.)
3) Keep the image the same size, but split it into several smaller textures which are all power of two. I.e. 320 = 256+64, 480 = 256+128+64+32.
1) is easiest. 2) requires data changes, to use the proper texture coordinates inset in the texture. 3) requires code changes, to draw multiple quads.
1) Resize the image to a power of two. If you resize down, you lose quality. Resizing up uses more memory.
2) Keep the image the same size, but put it inside of a larger power-of-two texture. You can put other things in the extra padding space (i.e. make a texture atlas.)
3) Keep the image the same size, but split it into several smaller textures which are all power of two. I.e. 320 = 256+64, 480 = 256+128+64+32.
1) is easiest. 2) requires data changes, to use the proper texture coordinates inset in the texture. 3) requires code changes, to draw multiple quads.
Personally, I prefer to use option 3 for uncompressed backgrounds (i.e. not when using pvrtc), since it uses less memory at the expense of a few extra calls, while memory is at a premium on iPhone.
Option 1 is definitely very easy. Here's an example of how you could do that:
And here's how you might use it:
Option 1 is definitely very easy. Here's an example of how you could do that:
Code:
GLuint backgroundTexture;
- (void)loadBackground
{
CGImageRef image;
CGContextRef imageContext;
GLubyte *imageData;
image = [UIImage imageNamed:@"Default.png"].CGImage;
if(image)
{
imageData = (GLubyte *)malloc(512 * 512 * 4); // four channels is only useful for images with alpha, so better to use 3 instead
imageContext = CGBitmapContextCreate(imageData, 512, 512, 8, 512 * 4, CGImageGetColorSpace(image), kCGImageAlphaPremultipliedLast);
CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, 512.0f, 512.0f), image);
CGContextRelease(imageContext);
glGenTextures(1, &backgroundTexture);
glBindTexture(GL_TEXTURE_2D, backgroundTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
free(imageData);
}
}And here's how you might use it:
Code:
- (void)drawView
{
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// draw background
const GLfloat backgroundVertices[] = {
-1.0f, -1.5f,
1.0f, -1.5f,
-1.0f, 1.5f,
1.0f, 1.5f,
};
const GLfloat backgroundTexCoords[] = {
0.0f, 1.0f,
1.0f, 1.0f,
0.0f, 0.0f,
1.0f, 0.0f,
};
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, squareTexCoords);
glVertexPointer(2, GL_FLOAT, 0, backgroundVertices);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, backgroundTexture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
Thanks a lot for your answers. At first, I tried to resize the image. The result was what I expected. Since I will use this method only once per level, I think I will pass on the rest of the methods. I may use them on other projects, though.
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Loading textures only when they're needed? | daveh84 | 5 | 2,459 |
Dec 1, 2009 10:14 AM Last Post: warmi |
|
| OpenGL ES Textures Start White | demonpants | 5 | 5,993 |
Sep 3, 2009 06:40 AM Last Post: Skorche |
|
| [Problem] Loading image with OpenGL orthogonal view pixel-to-pixel | Lexis | 2 | 3,225 |
Aug 21, 2009 01:35 AM Last Post: Lexis |
|
| opengl es font textures? | cool mr croc | 0 | 2,101 |
Aug 17, 2009 04:52 AM Last Post: cool mr croc |
|
| OpenGL textures upside down? | orbian | 1 | 5,606 |
Mar 13, 2009 02:53 PM Last Post: ThemsAllTook |
|

