OpenGL ES: Possible to use part of an image as a texture?

Discussion in 'iOS Programming' started by orangeiris, Sep 22, 2008.

  1. orangeiris macrumors newbie

    Joined:
    Sep 11, 2008
    #1
    Since Open GL requires the use of "power of 2" sized images, there must be a way to use only a portion of an image as an actual texture, but I can't for the life of me figure out how. I starting playing around with glTexSubImage2D, but got no where.

    I've taken the GL Sprite demo code and I'm trying to create a shape that will act as a background image. Since 320x480 is not a "power of 2" dimension, I can create a background by creating a 512x512 sized object and positioning it appropriately, but I'd rather create a 320x480 sized object and offset a 512x512 sized image within it to use as a texture. Can this be done?

    Here's the code I'm working with so far:

    Code:
    const GLfloat spriteVertices[] = {
    -1.6f, -1.6f,
    1.6f, -1.6f,
    -1.6f,  1.6f,
    1.6f,  1.6f,
    };
    
    const GLshort spriteTexcoords[] = {
    0, 0,
    1, 0,
    0, 1,
    1, 1,
    };
    Some setup code:

    Code:
    glVertexPointer(2, GL_FLOAT, 0, spriteVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    glTexCoordPointer(2, GL_SHORT, 0, spriteTexcoords);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    
    spriteImage = [UIImage imageNamed:@"BackgroundCopy.png"].CGImage;
    width = CGImageGetWidth(spriteImage);
    height = CGImageGetHeight(spriteImage);
    
    if (spriteImage) {
    	spriteData = (GLubyte *) malloc(width * height * 4);
    	spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
    	CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), spriteImage);
    	CGContextRelease(spriteContext);
    	
    	glGenTextures(1, &spriteTexture);
    	glBindTexture(GL_TEXTURE_2D, spriteTexture);
    	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);
    }
    
    Drawing code:

    Code:
    [EAGLContext setCurrentContext:context];
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);	
    glClear(GL_COLOR_BUFFER_BIT);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
    
     
  2. SqueegyX macrumors regular

    Joined:
    Mar 24, 2008
    #2
    I think the best way to do this is to change your texture coordinates. 0,0 is the top left, 1,1 is the bottom right. So if you had this:

    Code:
    const GLshort spriteTexcoords[] = {
      0,            0,
      480.0/512.0,  0,
      0,            320.0/512.0,
      480.0/512.0,  320.0/512.0,
    };
    or some variation therof, it should only show the 320x480 top left portion of your map.
     
  3. orangeiris thread starter macrumors newbie

    Joined:
    Sep 11, 2008
  4. ranReloaded macrumors 6502a

    ranReloaded

    Joined:
    Feb 16, 2010
    Location:
    Tokyo
    #4
    I think you better use these (s,t) tex coords:

    sMin = 0.5 / textureWidth;
    sMax = spriteWidth - 0.5 / textureWidth;
    tMin = 0.5 / textureHeight;
    tMax = spriteHeight - 0.5 / textureHeight;

    ...to sample each texel at the center and avoid sampling artifacts at the boundaries.

    (check this out)
     

Share This Page