Using odd-sized textures

Started by kstenerud, December 21, 2005, 06:48:16

Previous topic - Next topic

kstenerud

I'm a bit new to OpenGL and so this will probably be one of those newbie mistakes.

I'm writing an emulator in Java, and I'm having trouble setting up a system to handle sprites.
The various games I'm emulating have 8x8, 16x16, 24x24 sized sprites and so on (haven't even gotten to the non-square sprites yet!)

The problem is, how do I get something like 24x24 pixel data onto a texture, and correctly rendered to a surface?
Stretching the image to 32x32 is not an option since the emulated graphics engine may change the sprite contents on the fly.

I currently take the closest square (in this case 32x32) and then the emulator only writes in the top-left corner of the texture.  However, when I try to render my scene with a 24x24 unit square, I get a slightly squashed image in the top-left corner (as would be expected, since my original texture data is not 32x32).

I figured I could just get the size ratio and use that in the glTexCoord2f method, but it seems to only like 1.0f or 0.0f.

Is there some other way to get the "in-use" portion of the texture to take up the whole quad surface?

I currently wrap the texture with these hints:
       GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
       GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

Maybe there's some other wrap method that I can use?


Any help appreciated  :o

spasi

Quote from: "kstenerud"I figured I could just get the size ratio and use that in the glTexCoord2f method, but it seems to only like 1.0f or 0.0f.

That's the standard way to do it actually. Why do say that it only likes 1.0f or 0.0f? What's the problem exactly? Maybe you're confused by OpenGL's lower-left coordinate origin?

The other way is to use the ARB/NV/EXT_texture_rectangle extension or ARB_texture_non_power_of_two. If you go for the first one, remember that you'd have to specify unnormalized texture coordinates (0.0-24.0 instead of 0.0-1.0).

Quote from: "kstenerud"I currently wrap the texture with these hints:
       GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
       GL.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);

Maybe there's some other wrap method that I can use?

CLAMP_TO_EDGE should be the best wrap method for sprites.

kstenerud

Hmm, ok well I did the render scene like this:

       float ratioX = expectedX / textureX;
       float ratioY = expectedY / textureY;

       GL.glBegin(GL11.GL_QUADS);
       {
           // Not sure why I have to invert Y on the texture coordinates...
           GL.glTexCoord2f(0.0f, 0.0f); GL.glVertex2f(-expectedX/2, expectedY/2);  // Top Left Of The Texture and Quad
           GL.glTexCoord2f(0.0f, ratioY); GL.glVertex2f(-expectedX/2, -expectedY/2);  // Bottom Left Of The Texture and Quad
           GL.glTexCoord2f(ratioX, ratioY); GL.glVertex2f(expectedX/2, -expectedY/2);  // Bottom Right Of The Texture and Quad
           GL.glTexCoord2f(ratioX, 0.0f); GL.glVertex2f(expectedX/2, expectedY/2);  // Top Right Of The Texture and Quad
       }
       GL.glEnd();

expectedX and expectedY are the dimensions of the data I'm using to build the texture.
textureX and textureY are the actual dimensions of the texture (which is always >= expected).

If I use only 0.0f and 1.0f in glTexCoord2f, I get something on the screen, although it's slightly squashed.
If I use the ratios in place of 1.0f, I get nothing.
Just for kicks, I inverted the ratios to give values always <= 1.0, and it gives the same result as if I had put in 1.0f  :?

kstenerud

Another question:  If I use the odd-sized texture extensions, will that slow down the graphics engine?  Will I have compatibility problems on some cards?

kstenerud

Ok, I'm a moron.

I did this:
       int expectedX = width;
       int expectedY = height;
       int textureX = getPowerOf2(width);
       int textureY = getPowerOf2(height);

       float ratioX = expectedX / textureX;
       float ratioY = expectedY / textureY;

when I should have done:
       float ratioX = (float)expectedX / (float)textureX;
       float ratioY = (float)expectedY / (float)textureY;

spasi

Hehe, that's a common mistake. You should be careful when mixing primitive types.

Anyway, the XXX_texture_rectangle extensions may be a little slower than using standard POT textures. Nothing extreme though, probably not even measurable. Also, you should always check if the extension is available. The XXX_texture_rectangle extensions are widely supported, but not the ARB_texture_non_power_of_two.