Trying to render to texture using framebuffer always results in white texture - iphone

Using a couple of posts here in StackOverflow, I created what is supposed to be a simple render-to-texture using a framebuffer.
The problem here is that it's not working. Something is broken in the mix, as my final texture is just a white square. I am not getting any gl errors whatsoever. Here is my code.
Declare instance variables.
GLuint texture;
GLuint textureFrameBuffer;
Generate the texture and framebuffer.
glGetError();
//Generate the texture that we will draw to (saves us a lot of processor).
glEnable(GL_TEXTURE_2D);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// Use OpenGL ES to generate a name for the texture.
// Pass by reference so that our texture variable gets set.
glGenTextures(1, &texture);
// Bind the texture name.
glBindTexture(GL_TEXTURE_2D, texture);
// Specify a 2D texture image, providing a pointer to the image data in memory.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
//Create a frame buffer to draw to. This will allow us to directly edit the texture.
GLint oldFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);
glGenFramebuffersOES(1, &textureFrameBuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture, 0);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
NSLog(#"Error on framebuffer init. glError: 0x%04X", err);
}
Draw a big string into the framebuffer.
glGetError();
GLint oldFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &oldFBO);
//Bind our frame buffer.
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
//Clear out the texture.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Draw the letters to the frame buffer. (calls glDrawArrays a bunch of times, binds various textures, etc.) Does everything in 2D.
[self renderDialog:displayString withSprite:displaySprite withName:displaySpriteName];
//Unbind the frame buffer.
glBindFramebufferOES(GL_FRAMEBUFFER_OES, oldFBO);
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
NSLog(#"Error on string creation. glError: 0x%04X", err);
}
Draw it.
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glGetError();
//Draw the text.
[EAGLView enable2D];
//Push the matrix so we can keep it as it was previously.
glPushMatrix();
//Store the coordinates/dimensions from the rectangle.
float x = 0;
float y = [Globals getPlayableHeight] - dialogRect.size.height;
float w = [Globals getPlayableWidth];
float h = dialogRect.size.height;
// Set up an array of values to use as the sprite vertices.
GLfloat vertices[] =
{
x, y,
x, y+h,
x+w, y+h,
x+w, y
};
// Set up an array of values for the texture coordinates.
GLfloat texcoords[] =
{
0, 0,
0, h / 128,
w / 512, h / 128,
w / 512, 0
};
//Render the vertices by pointing to the arrays.
glVertexPointer(2, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
// Set the texture parameters to use a linear filter when minifying.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//Allow transparency and blending.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Enable 2D textures.
glEnable(GL_TEXTURE_2D);
//Bind this texture.
[EAGLView bindTexture:texture];
//Finally draw the arrays.
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
//Restore the model view matrix to prevent contamination.
glPopMatrix();
GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
NSLog(#"Error on draw. glError: 0x%04X", err);
}
Any external things I called work just fine in other contexts. Any ideas? I know almost nothing about framebuffers, so any help troubleshooting would be great.

Texture parameters are set on a per-texture basis. The code you posted appears to be setting GL_TEXTURE_MIN_FILTER before the texture you’re rendering to has been created or bound. If you’re not setting the filter anywhere else, and you haven’t specified texture images for the remaining levels, your texture is likely incomplete, which is why you’re getting white.
For future reference, the absence of GL errors after framebuffer setup does not mean that the framebuffer is usable for rendering. You should also check that the framebuffer is complete by calling glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) and verifying that GL_FRAMEBUFFER_COMPLETE_OES is returned.

Related

glFramebufferTexture2D fails on iPhone for certain texture sizes

When I try to attach a texture to a framebuffer, glCheckFramebufferStatus reports GL_FRAMEBUFFER_UNSUPPORTED for certain texture sizes. I've tested on both a 2nd and 4th generation iPod Touch. The sizes of texture that fail are not identical between the two models.
Here are some interesting results:
2nd generation - 8x8 failed, 16x8 failed, but 8x16 succeeded!
4th generation - 8x8 succeeded, 8x16 succeeded, but 16x8 failed!
Here's some code I used to test attaching textures of different sizes:
void TestFBOTextureSize(int width, int height)
{
GLuint framebuffer, texture;
// Create framebuffer
glGenFramebuffersOES(1, &framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
// Create texture
glGenTextures(1,&texture);
glBindTexture(GL_TEXTURE_2D,texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D,0);
// Attach texture to framebuffer
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, texture, 0);
GLenum error = glGetError();
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if (status==GL_FRAMEBUFFER_COMPLETE_OES)
NSLog(#"%dx%d Succeeded!",width,height,status);
else
NSLog(#"%dx%d Failed: %x %x %d %d",width,height,status,error,texture,framebuffer);
// Cleanup
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, 0, 0);
glDeleteTextures(1, &texture);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glDeleteFramebuffersOES(1, &framebuffer);
}
void TestFBOTextureSizes()
{
int width,height;
for (width=1; width<=1024; width<<=1)
{
for (height=1; height<=1024; height<<=1)
TestFBOTextureSize(width,height);
}
}
It seems that as long as both dimensions are at least 16 pixels then everything works ok on both devices. The thing that bothers me, though, is that I haven't seen anything written about texture size requirements for attaching to a framebuffer object. One solution, for now, would be to restrict my texture sizes to be at least 16 pixels, but might this break in the future or already be broken on some device I haven't tried? I could also perform this test code at startup in order to dynamically figure out which texture sizes are allowed, but that seems a bit hokey.
I have experienced similar problem, when I'm trying to render to texture with size 480x320 (full screen w/o resolution scale) on iPod touch 4. When I call glCheckFramebufferStatus() it returns GL_FRAMEBUFFER_UNSUPPORTED. My code:
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 480, 320, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
// report error
}
Investigating this problem I have found that GL_TEXTURE_2D has to be a valid OpenGL ES object if we want it to use in render-to-texture mechanism. This means texture should be ready for bound and use. So to fix an error I have to set some texture parameters. Because I use non-POT texture I have to set GL_TEXTURE_WRAP_ to GL_CLAMP_TO_EDGE (default value is GL_REPEAT) and GL_TEXTURE_MIN_FILTER to GL_NEAREST or GL_LINEAR (default value is GL_NEAREST_MIPMAP_LINEAR) to use this texture.
I couldn't find what's the problem with 16x8, but 16x9 and 17x8 works fine if this parameters are set. I hope this information will be helpful for you.

How to disable or configure clipping when rendering to texture using FBO in OpenGL?

I have a question about the way the FBO clips the visible scene.
All this happens in iPhone's OpenGL ES.
I'm rendering in 2D and using render-to-texture with FBO.
I find that when any part of the scene passes any side of the rectangle of screen size (480*320) that it appears clipped from the FBO generated texture.
Why does it do that? How do I disable or configure it?
I've tried disabling scissor test by
lDisable(GL_SCISSOR_TEST);
I've tried to set up needed section by
`glEnable(GL_SCISSOR_TEST);
glScissor(0, 0, 100, 100);`
I've tried to adjust Viewport by
glViewport(0,0, 512,512);
it doesn't work as needed. Instead of extending the render area to needed 512*512 it looks like it still clips the area to 480*320 and stretches it afterwards to 512*512
All these didn't bring needed result.
In my code:
I create the texture
GLuint textureID;
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);`
Create FBO and attach texture to it
GLuint textureFrameBuffer;
GLint prevFBO;
glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &prevFBO);
// create framebuffer
glGenFramebuffersOES(1, &textureFrameBuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, textureFrameBuffer);
// attach renderbuffer
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, textureID, 0);
if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
NSLog(#"ERROR - WHILE CREATING FBO");
// unbind frame buffer
glBindFramebufferOES(GL_FRAMEBUFFER_OES, prevFBO);
And then, when I draw some stuff to FBO and render the square with this texture,
static const float textCoords[] =
{
0, 1,
1, 1,
0, 0,
1, 0,
};
static const float quadVerts[] =
{
0, 320,
320, 320,
0, 0,
320, 0,
};
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, textureID);
glVertexPointer(2, GL_FLOAT, 0, quadVerts);
glTexCoordPointer(2, GL_FLOAT, 0, textCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
To my opinion I should see the square filled with all the stuff I had drawn to my FBO. Whereas, I only see a part of it – clipped rectangle of size 480x320 at lower left corner.
So, the question is steel actual
You need to change your viewport doing:
glViewport(0,0,textureWidth,textureHeight);
EDIT:
And don't forget to switch it back to its normal value after rendering onto your FBO.
/// save viewport
GLint vp[4];
glGetIntegerv(GL_VIEWPORT, vp);
/// restore viewport
glViewport(vp[0], vp[1], vp[2], vp[3]);

How can I draw (as in GLPaint) onto a background image, and with temporary drawings?

I am writing a GLPaint-esque drawing application for the iPad, however I have hit a stumbling block. Specifically, I am trying to implement two things at the moment:
1) A background image that can be drawn onto.
2) The ability to draw temporary shapes, e.g. you might draw a line, but the final shape would only be committed once the finger has lifted.
For the background image, I understand the idea is to draw the image into a VBO and draw it right before every line drawing. This is fine, but now I need to add the ability to draw temporary shapes... with kEAGLDrawablePropertyRetainedBacking set to YES (as in GLPaint) the temporary are obviously not temporary! Turning the retained backing property to NO works great for the temporary objects, but now my previous freehand lines aren't kept.
What is the best approach here? Should I be looking to use more than one EAGLLayer? All the documentation and tutorials I've found seem to suggest that most things should be possible with a single layer. They also say that retained backing should pretty much always be set to NO. Is there a way to work my application in such a configuration? I tried storing every drawing point into a continually expanding vertex array to be redrawn each frame, but due to the sheer number of sprites being drawn this isn't working.
I would really appreciate any help on this one, as I've scoured online and found nothing!
I've since found the solution to this problem. The best way appears to be to use custom framebuffer objects and render-to-texture. I hadn't heard of this before asking the question, but it looks like an incredibly useful tool for the OpenGLer's toolkit!
For those that may be wanting to do something similar, the idea is that you create a FBO and attach a texture to it (instead of a renderbuffer). You can then bind this FBO and draw to it like any other, the only difference being that the drawings are rendered off-screen. Then all you need to do to display the texture is to bind the main FBO and draw the texture to it (using a quad).
So for my implementation, I used two different FBOs with a texture attached to each - one for the "retained" image (for freehand drawing), and the other for the "scratch" image (for temporary drawings). Each time a frame is rendered, I first draw a background texture (in my case I just used the Texture2D class), then draw the retained texture, and finally the scratch texture if required. When drawing a temporary shape everything is rendered to the scratch texture, and this is cleared at the start of every frame. Once it is finished, the scratch texture is drawn to the retained texture.
Here are a few snippets of code that might be of use to somebody:
1) Create the framebuffers (I have only shown a couple here to save space!):
// ---------- DEFAULT FRAMEBUFFER ---------- //
// Create framebuffer.
glGenFramebuffersOES(1, &viewFramebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
// Create renderbuffer.
glGenRenderbuffersOES(1, &viewRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
// Get renderbuffer storage and attach to framebuffer.
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
// Check for completeness.
status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(#"Failed to make complete framebuffer object %x", status);
return NO;
}
// Unbind framebuffer.
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
// ---------- RETAINED FRAMEBUFFER ---------- //
// Create framebuffer.
glGenFramebuffersOES(1, &retainedFramebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, retainedFramebuffer);
// Create the texture.
glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
glGenTextures(1, &retainedTexture);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, retainedTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1024, 1024, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
// Attach the texture as a renderbuffer.
glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_TEXTURE_2D, retainedTexture, 0);
// Check for completeness.
status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(#"Failed to make complete framebuffer object %x", status);
return NO;
}
// Unbind framebuffer.
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
2) Draw to the render-to-texture FBO:
// Ensure that we are drawing to the current context.
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, retainedFramebuffer);
glViewport(0, 0, 1024, 1024);
// DRAWING CODE HERE
3) Render the various textures to the main FBO, and present:
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Clear to white.
glClear(GL_COLOR_BUFFER_BIT);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
[self drawBackgroundTexture];
[self drawRetainedTexture];
[self drawScratchTexture];
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
For example, drawing drawing the retained texture using [self drawRetainedTexture] would use the following code:
// Bind the texture.
glBindTexture(GL_TEXTURE_2D, retainedTexture);
// Destination coords.
GLfloat retainedVertices[] = {
0.0, backingHeight, 0.0,
backingWidth, backingHeight, 0.0,
0.0, 0.0, 0.0,
backingWidth, 0.0, 0.0
};
// Source coords.
GLfloat retainedTexCoords[] = {
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0
};
// Draw the texture.
glVertexPointer(3, GL_FLOAT, 0, retainedVertices);
glTexCoordPointer(2, GL_FLOAT, 0, retainedTexCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Unbind the texture.
glBindTexture(GL_TEXTURE_2D, 0);
A lot of code, but I hope that helps somebody. It certainly had me stumped for a while!

Strange colors when loading some textures with openGL for iphone

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);
}
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.

glError: 0x0501 when loading a large texture with OpenGL ES on the iPhone?

Here's the code I use to load a texture. image is a CGImageRef. After loading the image with this code, I eventually draw the image with glDrawArrays().
size_t imageW = CGImageGetWidth(image);
size_t imageH = CGImageGetHeight(image);
size_t picSize = pow2roundup((imageW > imageH) ? imageW : imageH);
GLubyte *textureData = (GLubyte *) malloc(picSize * picSize << 2);
CGContextRef imageContext = CGBitmapContextCreate( textureData, picSize, picSize, 8, picSize << 2, CGImageGetColorSpace(image), kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big );
if (imageContext != NULL) {
CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, (CGFloat)imageW, (CGFloat)imageH), image);
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
// when texture area is small, bilinear filter the closest mipmap
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
// when texture area is large, bilinear filter the original
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// the texture wraps over at the edges (repeat)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, picSize, picSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);
GLenum err = glGetError();
if (err != GL_NO_ERROR)
NSLog(#"Error uploading texture. glError: 0x%04X", err);
CGContextRelease(imageContext);
}
free(textureData);
This seems to work fine when the image is 320x480, but it fails when the image is larger (for example, picSize = 2048).
Here's what I get in the Debugger Console:
Error uploading texture. glError: 0x0501
What's the meaning of this error? What's the best workaround?
Aren’t you simply hitting the maximum texture size limit? The error code is GL_INVALID_VALUE, see the glTexImage2D docs:
GL_INVALID_VALUE is generated if width
or height is less than 0 or greater
than 2 + GL_MAX_TEXTURE_SIZE, or if
either cannot be represented as
2k+2(border) for some integer value of
k.
iPhone does not support textures larger than 1024 pixels. The workaround is to split the image into several textures.
Maybe you are simply running out of memory - did you verify the value returned from malloc() is not NULL?
(this could explain getting 0x0501, which is GL_INVALID_VALUE).
I also experienced the same kind of issue with GLKitBaseEffect, it seemed to be a memory issue (as Hexagon proposed). To fix this, I had to add manual texture release calls:
GLuint name = self.texture.name;
glDeleteTextures(1, &name);
See this thread for more: Release textures (GLKTextureInfo objects) allocated by GLKTextureLoader.