same texture binding on every "quad" - ios

I have 6 squares made up of 2 trangles, each of which is supposed to have a different texture mapped onto it. Instead, each texture is having the last binded texture on it instead of its own. Heres my drawView and setView:
- (void)drawView:(GLView*)view
{
glBindTexture(GL_TEXTURE_2D, texture[0]);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
static const Vertex3D vertices[] = {
{0,0, 1}, //TL
{ 1024,0, 1}, //TR
{0,-1024, 1}, //BL
{ 1024.0f, -1024.0f, 1} //BR
};
static const GLfloat texCoords[] = {
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0
};
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
- (void)setupView:(GLView*)view {
// Bind the number of textures we need.
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_GENERATE_MIPMAP,GL_TRUE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glLoadIdentity();
NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:#"jpg"];
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
UIImage *image = [[UIImage alloc] initWithData:texData];
if (image == nil)
NSLog(#"Do real error checking here");
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc( height * width * 4 );
CGContextRef context = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
// Flip the Y-axis
CGContextTranslateCTM (context, 0, height);
CGContextScaleCTM (context, 1.0, -1.0);
CGColorSpaceRelease( colorSpace );
CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CGContextRelease(context);
free(imageData);
}

You're always using texture[0], so you will indeed get the same texture every time. You need to pass the id of the texture you want to glBindTexture ().

I think the problem is related to the texture binding and in particular to this line:
glBindTexture(GL_TEXTURE_2D, texture[0]);
Double check that you use the right value of the gluint required for the texture binding.
Are you using shaders? In case double check it as well though it is most probably not the case.
I suggest to use texture atlas in order to not kill the overall engine's performances by binding every time a different texture in the GPU.

Related

Simple 2d texture render

I've been trying for the last two and a half hours to get a simple 2D texture renderer working using opengl es on ios. I've tried following this tutorial to no avail. I've checked my gl errors , checked my triangle ordering, even tried switching back to ES1 to use the fixed function pipeline to absolutely no avail. I'm at a complete loss here, what is going wrong? For completeness' sake, here is my setup and draw code:
- (void)setupGL
{
[EAGLContext setCurrentContext:self.context];
GLenum err = 0;
glEnable(GL_TEXTURE_2D);
CHECK_GL_ERR();
glEnable(GL_BLEND);
CHECK_GL_ERR();
glBlendFunc(GL_ONE, GL_SRC_COLOR);
CHECK_GL_ERR();
glGenTextures(1, &texture);
CHECK_GL_ERR();
glBindTexture(GL_TEXTURE_2D, texture);
CHECK_GL_ERR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
CHECK_GL_ERR();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
CHECK_GL_ERR();
UIImage *image = [UIImage imageNamed:#"GL_Target"];
if (image == nil)
NSLog(#"Do real error checking here");
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc( height * width * 4 );
CGContextRef context = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGColorSpaceRelease( colorSpace );
CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
CGContextTranslateCTM( context, 0, height - height );
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CHECK_GL_ERR();
CGContextRelease(context);
free(imageData);
effect = [[GLKBaseEffect alloc] init];
}
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
GLfloat rot = 0.0;
GLenum err = 0;
glColor4f(0.0, 0.0, 0.0, 0.0);
CHECK_GL_ERR();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
CHECK_GL_ERR();
glEnableClientState(GL_VERTEX_ARRAY);
CHECK_GL_ERR();
glEnableClientState(GL_NORMAL_ARRAY);
CHECK_GL_ERR();
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
CHECK_GL_ERR();
static const GLfloat vertices[] = {
-1.0, 1.0, -0.0,
1.0, 1.0, -0.0,
-1.0, -1.0, -0.0,
1.0, -1.0, -0.0
};
static const GLfloat normals[] = {
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0,
0.0, 0.0, 1.0
};
static const GLfloat texCoords[] = {
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0
};
glLoadIdentity();
CHECK_GL_ERR();
glTranslatef(0.0, 0.0, -3.0);
CHECK_GL_ERR();
glRotatef(rot, 1.0, 1.0, 1.0);
CHECK_GL_ERR();
glBindTexture(GL_TEXTURE_2D, texture);
CHECK_GL_ERR();
glVertexPointer(3, GL_FLOAT, 0, vertices);
CHECK_GL_ERR();
glNormalPointer(GL_FLOAT, 0, normals);
CHECK_GL_ERR();
glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
CHECK_GL_ERR();
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
CHECK_GL_ERR();
glDisableClientState(GL_VERTEX_ARRAY);
CHECK_GL_ERR();
glDisableClientState(GL_NORMAL_ARRAY);
CHECK_GL_ERR();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
CHECK_GL_ERR();
static NSTimeInterval lastDrawTime;
if (lastDrawTime)
{
NSTimeInterval timeSinceLastDraw = [NSDate timeIntervalSinceReferenceDate] - lastDrawTime;
rot+= 60 * timeSinceLastDraw;
}
lastDrawTime = [NSDate timeIntervalSinceReferenceDate];
}
EDIT
After scrapping that approach, I am now trying to mirror this project because I was actually able to get that to build, run, and render on my machine. I started by copying the code I thought was important, then copied line by line, then copied entire file contents, then copied entire files, and then created a brand new project, copied over the view controller, sprite, and storyboard files and it still doesn't work. What part of project setup am I missing that is making new projects not work with 100% the exact same code as a project that does work?
From just that code, it seems you are missing binding the shaders.
glUseProgram(program);
Also make sure your shaders compile without error when you run the program.
The author of that blog has also a sample OpenGL ES 2.0 project for XCode in github. Please take a look at it, https://github.com/jlamarche/iOS-OpenGLES-Stuff

Memory leak in drawing OpenGL framebuffer to UIImage

I am using OpenGL to do my drawing on screen and want to draw a portion of the screen to a UIImage. This is code I've cobbled together looking at examples, which works, but produces a memory leak every time it's called. I've tested this on device and the leak still persists and eventually causes a crash. The returned UIImage is saved to an instance variable and is later definitely set to nil again. What is causing the memory leak here?
- (UIImage *)renderToImageWithContentFrame:(CGRect)contentFrame
exportFrame:(CGRect)exportFrame
scale:(float)scale {
float screenWidth = contentFrame.size.width * scale;
float screenHeight = contentFrame.size.height * scale;
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
GLuint renderTex;
glGenTextures(1, &renderTex);
glBindTexture(GL_TEXTURE_2D, renderTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, screenWidth, screenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, renderTex, 0);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(0, 0, screenWidth, screenHeight);
[self _renderImageGL];
// grabbing image from FBO
NSInteger dataLength = screenWidth * screenHeight * 4;
GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(0, 0, screenWidth, screenHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
glDeleteFramebuffers(1, &framebuffer);
CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGImageRef iref = CGImageCreate(screenWidth, screenHeight, 8, 32, screenWidth * 4, colorspace,
kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
ref, NULL, true, kCGRenderingIntentDefault);
float x = (exportFrame.origin.x - contentFrame.origin.x) * scale;
float y = (exportFrame.origin.y - contentFrame.origin.y) * scale;
float width = exportFrame.size.width * scale;
float height = exportFrame.size.height * scale;
CGImageRef cropped = CGImageCreateWithImageInRect(iref, (CGRect){x, y, width, height});
UIGraphicsBeginImageContext((CGSize){width, height});
CGContextRef cgcontext = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(cgcontext, kCGBlendModeCopy);
CGContextDrawImage(cgcontext, (CGRect){0, 0, width, height}, cropped);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
free(data);
CFRelease(ref);
CFRelease(colorspace);
CGImageRelease(iref);
CGImageRelease(cropped);
return image;
}
The variable renderTex is not being freed (via a call to glDeleteTextures(1, &renderTex);). My guess is that Instruments may not know about OpenGL-allocated memory because that memory may reside on a graphics card and may be harder (or impossible) to track. (Though that's mainly a guess.)

iOS OPENGL Texture GL_REPEAT repeats only two times

I have a OpenGL program for iOS.
I would like to have a repeated texture. Normaly this is not a big deal for me, because GL_REPEAT does a fine job.
You can see the problem comparing the next two images:
First image is simulator screenshot. Everything works fine.
Second image is iPad screenshot. The textur will be repeated once and the clamped to edge.
Notice that the image is repeated 4 times in each direction. The red area is the area where the texture coordinate in a direction is > 1.0. So the device shows the image (normal area) repeats the image (red area) and than clamps the image.
So I will show what I do to render the Quad.
I setup the texture
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
_location = location;
_texture = [self setupTextureByUIImage:[UIImage imageNamed:name]];
_uniform = uniform;
The setUpTextureByUIImage function is
- (GLuint) setupTextureByUIImage: (UIImage*) image {
// We want to display images
glActiveTexture(_location);
GLuint texture;
// Generate textures
glGenTextures(1, &texture);
// Bind it
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
// Get Image size
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Allocate memory for image
void *imageData = malloc( height * width * 4 );
CGContextRef imgcontext = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGColorSpaceRelease( colorSpace );
CGContextClearRect( imgcontext, CGRectMake( 0, 0, width, height ) );
CGContextTranslateCTM( imgcontext, 0, height - height );
CGContextDrawImage( imgcontext, CGRectMake( 0, 0, width, height ), image.CGImage );
// Generate texture in opengl
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
// Release context
CGContextRelease(imgcontext);
// Free Stuff
free(imageData);
return texture;
}
After setup I begin to draw an object.
First I call makeActiveAndBind.
Then I draw.
Then I call unbind.
- (void) makeActiveAndBind
{
glActiveTexture(_location);
glBindTexture(GL_TEXTURE_2D, _texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glUniform1i(_uniform, _location - GL_TEXTURE0);
}
- (void) unbind
{
glBindTexture(GL_TEXTURE_2D, 0);
}
Does anyone have any idea to this strange behavior?
The texture coordinates of the cube are [0,4]x[0,4]

opengl es(iphone) render from file

sorry for my english
I want to display video from a file, where the frames of 4 bytes per pixel, BRGA, 1280x720?
on mac I just took out the frame and drew this glDrawPixels, running on a Mac but in opengl es all differently.
here's the code from the mac
int pos = 0;
NSData *data = [[NSData alloc] initWithContentsOfFile:#"video.raw"];
glViewport(0,0,width,height);
glLoadIdentity();
glOrtho(0, width, 0, height, -1.0, 1.0);
glPixelZoom(1, -1);
glClear(GL_COLOR_BUFFER_BIT);
//glRasterPos2i(0, height);
glRasterPos2i(0, 0);
glDrawPixels(1280, 720, GL_BGRA, GL_UNSIGNED_BYTE, [data bytes]+pos);
glFinish();
Push those data to texture with "glTexSubImage2D" and render the texture. Note though that texture has to be of power of 2 so for your case you can make it (2048, 1024) but you may update only the (1280, 720) part:
CGSize videoSize;
CGSize textureSize;
GLuint dimension = 1;
while (videoSize.width > dimension) {
dimension <<= 1;
}
textureSize = CGSizeMake(dimension, .0f);
dimension = 1;
while (videoSize.height > dimension) {
dimension <<= 1;
}
textureSize = CGSizeMake(textureSize.width, dimension);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureSize.width, textureSize.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
GLfloat textureCoordinates[] = {
.0f, .0f,
.0f, videoSize.height/textureSize.height,
videoSize.width/textureSize.width, .0f,
videoSize.width/textureSize.width, videoSize.height/textureSize.height
};
To update the texture:
void *data;
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, videoSize.width, videoSize.height, GL_RGBA, GL_UNSIGNED_BYTE, data);
Then just draw your textured quad.

Trouble Displaying Textures OpenGL ES 1.1

I'm working on a simple little game for the iPhone, and I'd like to use textures, however I can't quite seem to get it working...
After some research I found this page and this site. Both are great references, and taught me a little bit about textures, however, after loading a texture using either function I can't get the texture displayed, here's what my code looks like:
Very Simple Texture Display Function (not working)
void drawTexture(GLuint texture, float x, float y, float w, float h)
{
glBindTexture(GL_TEXTURE_2D,texture);
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0,box);
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Normally, I'd not create an array every single frame only to display an image, but this is just an example. When I run this function, I get nothing. Blank- no image, nothing (unless of course I'd previously enabled a color array and hadn't disabled it afterwards)
Second Simple Display Function (this one uses a quick little class)
void draw_rect(RectObject* robj){
glVertexPointer(2, GL_FLOAT, 0, [robj vertices]);
glEnableClientState(GL_VERTEX_ARRAY);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, [robj colors]);
glEnableClientState(GL_COLOR_ARRAY);
if ([robj texture] != -1){
glEnable(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glClientActiveTexture([robj texture]);
glTexCoordPointer(2, GL_FLOAT, 0, defaultTexCoord);
glBindTexture(GL_TEXTURE_2D, [robj texture]);
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisable(GL_TEXTURE_2D);
glDisable(GL_TEXTURE_COORD_ARRAY);
}
This function on the other hand, does change the display, instead of outputting the texture however it outputs a black square...
Setup Background
In my init function I'm calling
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_SRC_COLOR);
Two LONG Texture Loading Functions
struct Texture2D LoadImage(NSString* path)
{
struct Texture2D tex;
tex.texture = -1;
// Id for texture
GLuint texture;
// Generate textures
glGenTextures(1, &texture);
// Bind it
glBindTexture(GL_TEXTURE_2D, texture);
// Set a few parameters to handle drawing the image
// at lower and higher sizes than original
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
//NSString *path = [[NSString alloc] initWithUTF8String:imagefile.c_str()];
path = [[NSBundle mainBundle] pathForResource:path ofType:#""];
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
UIImage *image = [[UIImage alloc] initWithData:texData];
if (image == nil)
return tex;
// Get Image size
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Allocate memory for image
void *imageData = malloc( height * width * 4 );
CGContextRef imgcontext = CGBitmapContextCreate(
imageData, width, height, 8, 4 * width, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGColorSpaceRelease( colorSpace );
CGContextClearRect( imgcontext,
CGRectMake( 0, 0, width, height ) );
CGContextTranslateCTM( imgcontext, 0, height - height );
CGContextDrawImage( imgcontext,
CGRectMake( 0, 0, width, height ), image.CGImage );
// Generate texture in opengl
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
// Release context
CGContextRelease(imgcontext);
// Free Stuff
free(imageData);
[image release];
[texData release];
// Create and return texture
tex.texture=texture;
tex.width=width;
tex.height=height;
return tex;
}
GLuint makeTexture(NSString* path){
GLuint texture[1]={-1};
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
path = [[NSBundle mainBundle] pathForResource:path ofType:#"png"];
NSData *texData = [[NSData alloc] initWithContentsOfFile:path];
UIImage *image = [[UIImage alloc] initWithData:texData];
if (image == nil)
NSLog(#"Do real error checking here");
GLuint width = CGImageGetWidth(image.CGImage);
GLuint height = CGImageGetHeight(image.CGImage);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
void *imageData = malloc( height * width * 4 );
CGContextRef context = CGBitmapContextCreate( imageData, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big );
CGColorSpaceRelease( colorSpace );
CGContextClearRect( context, CGRectMake( 0, 0, width, height ) );
CGContextTranslateCTM( context, 0, height - height );
CGContextDrawImage( context, CGRectMake( 0, 0, width, height ), image.CGImage );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
CGContextRelease(context);
free(imageData);
[image release];
[texData release];
return texture[0];
}
If you could point me in the right direction it would be much appreciated.
First of all, your draw_rect function has an error. Don't call glClientActiveTexture, it is used for multi-texturing and you don't need it. Calling it with a texture object will either bind some really strange texture unit or, most likely, result in an error.
And in the drawTexture function you are actually drawing the triangles in clockwise order. Assuming you didn't flip the y-direction in the projection matrix or something similar, if you have back-face culling enabled your whole geometry will get culled away. Try calling glDisable(GL_CULL_FACE), although back-face culling should be disabled by default. Or even better, change your vertices to counter-clockwise ordering:
box[] = { x,y+h, x,y, x+w,y+h, x+w,y };
You also have a mismatch of texture coordinates to vertices in your drawTexture function, but this shouldn't cause the texture not to be drawn, but rather just look a bit strange. Considering the changes to counter-clockwise ordering from the last paragraph, the texture coordinates should be:
tex[] = { 0.0f,1.0f, 0.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f };
EDIT: Your draw_rect function is also messing up the state, because you enable the vertex and color arrays, but then don't disable them again when you are finished with rendering. When you now want to draw something different without a color array (like in drawTexture), the color array is still enabled and uses some arbitrary data. So you should add
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
right after
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
in draw_rect.
EDIT: And you should also wrap the drawTexture function in a pair of glEnable(GL_TEXTURE_2D) and glDisable(GL_TEXTURE_2D). You enable texturing in the initialization code, which is wrong. You should set all neccessary state right before rendering, especially such highly object-dependent state like texturing. For example once you call draw_rect before drawTexture, you end up with disabled texturing, although you enabled it in the initialization code and thought it to be always enabled. Do you see that this is not a good idea?
EDIT: I just spotted another error. In draw_rect you call glEnable and glDisable with GL_TEXTURE_COORD_ARRAY, which is wrong. You have to use glEnableClientState and glDisableClientState for enabling/disabling vertex arrays, like you did int drawTexture.
So as a little mid-way conclusion your functions should actually look like:
void drawTexture(GLuint texture, float x, float y, float w, float h)
{
glBindTexture(GL_TEXTURE_2D,texture);
glEnable(GL_TEXTURE_2D);
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, box);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
void draw_rect(RectObject* robj)
{
if ([robj texture] != -1)
{
glBindTexture(GL_TEXTURE_2D, [robj texture]);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(2, GL_FLOAT, 0, defaultTexCoord);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glColorPointer(4, GL_UNSIGNED_BYTE, 0, [robj colors]);
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, [robj vertices]);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
if ([robj texture] != -1)
{
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
}
If one of the textures work and the other not, could it be a problem with the texture file ?
Dimensions sometimes can trick you, try to use the same file (the one working) on both textures and see if that solved. If it does it's a problem with the texture file.
The fun does work.
void drawTexture(GLuint texture, float x, float y, float w, float h)
{
glBindTexture(GL_TEXTURE_2D,texture);
glEnable(GL_TEXTURE_2D);
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, box);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
}
but we should relate to the right coordinate for texture. wo should change the code
form
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
to
GLfloat box[] = {x,y+h, x+w,y+h, x,y, x+w,y};
GLfloat tex[] = { 0.0f,1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f };
Thanks stackoverflow. Thanks your help.
Good luck!

Resources