Iphone – Strange colors when loading some textures with openGL for iphone

iphoneopengl

I'm writting a 2d game in Iphone, which uses textures as sprites, I'm getting colored noise around some of the images I render ( but such noise never appears over the texture Itself, only in the transparent portion around It). The problem does not happen with the rest of my textures. This is the code I use to load textures:

- (void)loadTexture:(NSString*)nombre {

CGImageRef textureImage = [UIImage imageNamed:nombre].CGImage;
if (textureImage == nil) {
NSLog(@"Failed to load texture image");
return;
}

textureWidth = NextPowerOfTwo(CGImageGetWidth(textureImage));   
textureHeight = NextPowerOfTwo(CGImageGetHeight(textureImage));

imageSizeX= CGImageGetWidth(textureImage);
imageSizeY= CGImageGetHeight(textureImage);

GLubyte *textureData = (GLubyte *)malloc(textureWidth * textureHeight * 4); 

CGContextRef textureContext = CGBitmapContextCreate(textureData, textureWidth,textureHeight,8, textureWidth * 4,CGImageGetColorSpace(textureImage),kCGImageAlphaPremultipliedLast);
CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)textureWidth, (float)textureHeight), textureImage);

CGContextRelease(textureContext);

glGenTextures(1, &textures[0]);

glBindTexture(GL_TEXTURE_2D, textures[0]);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);

free(textureData);

glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

glEnable(GL_BLEND);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);   

}

Best Answer

Your memory is not zeroed out before you draw the image in it. The funny pixels you see is old data in the transparent regions of your image. Use calloc instead of malloc (calloc returns zeroed memory).

You can also use CGContextSetBlendMode(textureContext, kCGBlendModeCopy); before drawing the image.

If you want to know the whole story:

This problem exists only for small images due to the fact that malloc has different code paths for small allocation sizes. It returns a small block from a pool it manages in user space. If the requested size is larger than a certain threshold (16K, I believe), malloc gets the memory from the kernel. The new pages are of course zeroed out.

It took me a while to figure that out.

Related Topic