OpenGL Image Textures

Member
Posts: 281
Joined: 2009.04
Post: #1
I am writing an OpenGL game in C, and I feel it would be much better if i could use textures. I have tried to muddle together some libpng stuff, but it's all too complicated.

I can see how to actually write tex coordinates on a quad, but I don't see how to load the image.

I'd be happy with any format bar JPEG or GIF, for obvious reasons.

Can someone help?

Thanks

~ Bring a Pen ~
Quote this message in a reply
⌘-R in Chief
Posts: 1,256
Joined: 2002.05
Member
Posts: 281
Joined: 2009.04
Post: #3
Yes, I've seen that before, but that makes use of <glaux.h>, which is windows only. Sad
It's not really the actual textures I'm stuck with, it's getting the image into an OpenGL texture.

~ Bring a Pen ~
Quote this message in a reply
⌘-R in Chief
Posts: 1,256
Joined: 2002.05
Post: #4
Quote:Yes, I've seen that before, but that makes use of <glaux.h>, which is windows only.

There's Mac OS X code at the bottom of every NeHe tutorial.

Also, if you search these forums, Apple examples, and the net in general, you'll find lots of texture loading code. It comes up often.
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #5
Yes, I have looked at the OSX code for that tutorial, but I don't understand it, and when I try and copy it, I get loads of errors. As for Apple examples... Well, the amount of code that's not ObjC, and not Legacy is small. Still, I'll look again...

~ Bring a Pen ~
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #6
... Nope. Can't find anything that's not C++ or ObjC or Windows or Linux. Sad Can you help?

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #7
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #8
Sorry if I seem stupid, but I don't get any of these. The ObjC just confuses things. And I don't even know what CGImage is. I find the Apple code is all too... politically correct, so much so It becomes unreadable.

~ Bring a Pen ~
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #9
You can't expect to understand something this involved when you spend less than an hour reading about it. If there's a part of the API that doesn't make sense to you (for example, if you don't know what a CGImage is), look it up in Apple documentation and keep reading until you do understand it. If you don't have the patience or dedication to do that, programming may not be an appropriate hobby for you.
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #10
I might put something together. Ninja

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
Sage
Posts: 1,403
Joined: 2005.07
Post: #11
I've made a tool for putting images into C source code for OpenGL. To compile the tool use:

gcc OpenGLTextureMaker.m -framework Cocoa -o OpenGLTextureMaker

Code:
#import <Cocoa/Cocoa.h>

#define ensure(conditional, error) if(!(conditional)) { NSLog(error); return 0; }
#define nl puts("");
#define indent printf("  ");

void datadump(int n, unsigned char * data) {
    printf("{");
    while(1) {
        printf("0x%X", *data);
        if(--n) printf(", ");
        else break;
        data++;
    }
    printf("};");
    nl;
}

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
    ensure(argc == 2, @"Provide an image as the command line parameter");
    
    NSBitmapImageRep * im =
        [[NSBitmapImageRep alloc]
            initWithData:
                [NSData dataWithContentsOfFile:[NSString stringWithUTF8String:argv[1]]]];
    
    ensure(im, @"Image not found or invalid");
    ensure([im samplesPerPixel] == 3, @"Image has more (or less) than 3 channels");
    ensure([im bitsPerPixel] == 3*8, @"Image has more than one byte per channel");
    
    printf("void $name_texture() {"); nl;
    indent; printf("unsigned char $name_texture_data[] ="); nl;
    datadump([im pixelsWide] * [im pixelsHigh] * 3, [im bitmapData]);
    indent; printf("glTexImage2D(GL_TEXTURE_2D,"); nl;
    indent; printf("             0,"); nl;
    indent; printf("             3,"); nl; // or maybe 4?
    indent; printf("             %d,", [im pixelsWide]); nl;
    indent; printf("             %d,", [im pixelsHigh]); nl;
    indent; printf("             0,"); nl;
    indent; printf("             GL_RGB,"); nl; // or maybe RGBA?
    indent; printf("             GL_UNSIGNED_BYTE,"); nl;
    indent; printf("             $name_texture_data);"); nl;
    indent; printf("glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);"); nl;
    indent; printf("glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);"); nl;
    printf("}"); nl;
    
    [pool drain];
    return 0;
}

run it like this:

./OpenGLTextureMaker example_image.png > output.txt

fix the output up and then paste it into

Code:
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>

/// SNIP
// paste the program output here
/// SNIP

void display(void) {
  glClearColor(0,0,0,1);
  glClear(GL_COLOR_BUFFER_BIT);
  glColor3f(1,1,1);
  
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  
  example_texture();
  glEnable(GL_TEXTURE_2D);
  
  glBegin(GL_QUADS);
  glTexCoord2f(0, 0);
  glVertex2f(-1,-1);
  glTexCoord2f(1, 0);
  glVertex2f( 1,-1);
  glTexCoord2f(1, 1);
  glVertex2f( 1, 1);
  glTexCoord2f(0, 1);
  glVertex2f(-1, 1);
  glEnd();
  
  glutSwapBuffers();
}

int main(int argc, char ** argv) {
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
  glutInitWindowPosition(100,100);
  glutInitWindowSize(512,512);
  glutCreateWindow("texture example");
  glutDisplayFunc(display);
  glutMainLoop();
  
  return 0;
}

and compile that using:
gcc -framework GLUT -framework OpenGL textureexample.c -o textureexample

to see it working.

Edit: Remember to use textures that have dimensions that are powers of two!

Sir, e^iπ + 1 = 0, hence God exists; reply!
Quote this message in a reply
⌘-R in Chief
Posts: 1,256
Joined: 2002.05
Post: #12
mikey Wrote:Yes, I have looked at the OSX code for that tutorial, but I don't understand it

Which is normally where you ask a question about the code, not ask for different code. What makes you think you'll understand different code anymore than the working code you've already seen?

Quote:and when I try and copy it, I get loads of errors.

Well, that's your fault, not the code's. Smile

And again, this would be something you'd ask a question about. You're clearly missing something important and relevant that you'd likely miss with any other code.


Quote:As for Apple examples... Well, the amount of code that's not ObjC, and not Legacy is small.

Likability/usefulness of specific APIs aside, there's no reason to avoid Obj-C just because it's "not C". You can easily use the two together, and having platform-specific code in a cross platform app is common. The language shouldn't be an issue.

And there's always third party code like SDL_image that you could use.
Quote this message in a reply
Member
Posts: 281
Joined: 2009.04
Post: #13
Thankyou very much unknown! GrinRaspSmileSmileSmile

FreakSoftware:

Yes, you're probably right. Thanks anyway though. Wink

Quote:You can't expect to understand something this involved when you spend less than an hour reading about it. If there's a part of the API that doesn't make sense to you (for example, if you don't know what a CGImage is), look it up in Apple documentation and keep reading until you do understand it. If you don't have the patience or dedication to do that, programming may not be an appropriate hobby for you.

You're right. I'm rushing. Thanks.

~ Bring a Pen ~
Quote this message in a reply
Member
Posts: 65
Joined: 2009.01
Post: #14
[INDENT]I've been researching this topic for a tutorial that I am working on. I am surprised at how little there is currently available on this topic. Here are my findings:[/INDENT]
[INDENT] In the Apple sample code there is the Texture2D class that will load an image as a texture, resize it as needed, invert it, and display it on a quad. The problem is that it freely mixes OpenGL with Objective-C, which makes it very fragile and problematic for beginners. Then there is the image loading code from the GLSprite sample code, which is easier to understand, but also rather fragile since it requires that the source image be in the right format and a power of two size, otherwise nothing will show up onscreen.[/INDENT]
In the end, I came up with this hybrid code:
Code:
    glGenTextures(1, &textureID);            
    
    CGImageRef image;
    CGContextRef spriteContext;
    GLubyte *spriteData;
    size_t    width, height;
    
    image = [UIImage imageNamed:@"puck.png"].CGImage;
    width = CGImageGetWidth(image);
    height = CGImageGetHeight(image);
    
    if(image) {
        spriteData = (GLubyte *) malloc(width * height * 4);        
        spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, CGImageGetColorSpace(image), kCGImageAlphaPremultipliedLast);
        //these next two lines are necessary because the iPhone has its y-axis upside down, so everything looks flipped    
        CGContextTranslateCTM(spriteContext, 0.0, height); //i.e., move the y-origin from the top to the bottom
        CGContextScaleCTM(spriteContext, 1.0, -1.0); //i.e., invert the y-axis        
        CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), image);
        CGContextRelease(spriteContext);        
        glBindTexture(GL_TEXTURE_2D, textureID);    // first Bind creates the texture and assigns a numeric name to it
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
        free(spriteData);        
        
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);        
        glEnable(GL_TEXTURE_2D);
        glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);    
        glEnable(GL_BLEND);    
    }

which loads an image that can then be draw using something like this:
Code:
    glBindTexture(GL_TEXTURE_2D, textureID);    
    glVertexPointer(2, GL_FLOAT, 0, puckVertices);
    glTexCoordPointer(2, GL_SHORT, 0, texCoords);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);//actually draw something on the screen
[INDENT]While this also mixes OpenGL and Objective-C and is not very robust in dealing with image formats, it nevertheless is easier for a beginner to understand. You can see that Core Graphics calls are being used to load the image data into memory, which is then passed as a pointer (spriteData) to OpenGL, which then takes over the responsibility for getting it to appear onscreen.[/INDENT]
Quote this message in a reply
Member
Posts: 87
Joined: 2006.08
Post: #15
Why are you enabling blending?

Also, please hoist the line that sets GL_TEXTURE_MIN_FILTER to occur before the call to glTexImage2D. It is correct either way, but setting the min filter before creating texture level 0 may allow GL to operate more efficiently.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  [SOLVED]OpenGL edges of textures mk12 2 4,396 Sep 2, 2010 08:07 PM
Last Post: mk12
  Dealing with inverted textures in OpenGL johncmurphy 7 7,027 Jun 15, 2009 08:11 AM
Last Post: Skorche
  Using textures OpenGL switches to software renderer bruno 2 3,561 Oct 12, 2008 03:06 AM
Last Post: bruno
  Loading and using textures with alpha in OpenGL with Cocoa corporatenewt 4 6,202 Dec 8, 2007 02:06 PM
Last Post: Malarkey
  loading textures - cocoa openGL mDmarco 20 9,384 Aug 28, 2007 08:48 PM
Last Post: OneSadCookie