Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

orangeiris

macrumors newbie
Original poster
Sep 11, 2008
11
0
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];
 
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.
 
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.

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)
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.