Texture doesnt match in size [SOLVED]

Started by daniel_nieto, February 25, 2011, 07:25:27

Previous topic - Next topic

daniel_nieto

i'm a newbie in OpenGL and I use SlickUtil to load a texture and binding it to a quad (to make it look like a 2D sprite), but the texture doesnt seem to fill the whole quad, the image is PNG with transparency, it is 200x200, so i draw a quad of this size, but the texture seems to be 256x256 when i load it, so it shrinks to "fit" my quad, and the result is a 200x200 quad with a small texture on it, i post an image to show you how it looks, i disabled GL_BLEND so you can see the texture without transparency... it should be just the ball inside a white plane, but as you can see it's not. What can I do to fix this problem with my 2D sprites?

ouattwtym

I know why, I think. Slick contains this code in InternalTextureLoader

    /**
     * Get the closest greater power of 2 to the fold number
     * 
     * @param fold The target number
     * @return The power of 2
     */
    public static int get2Fold(int fold) {
        int ret = 2;
        while (ret < fold) {
            ret *= 2;
        }
        return ret;
    } 
   


which gets called when the texture is made

        // produce a texture from the byte buffer
        GL.glTexImage2D(target, 
                      0, 
                      dstPixelFormat, 
                      get2Fold(width), 
                      get2Fold(height), 
                      0, 
                      srcPixelFormat, 
                      SGL.GL_UNSIGNED_BYTE, 
                      textureBuffer);


so your 200 pixel 2D sprite becomes a 256 pixel texture.

It is a requirement, at least on old graphics hardware, that all textures had "two to the power something" width and height and Slick enforces this for you.

Knowing this you'd need to paint your quad using only to top corner of your texture. I'm a big OpenGL noob myself though so can't advise how but maybe someone else can ...

jediTofu

Yes, this is the same for newer hardware AFAIK.  Generally, you just pad your image with black pixels up to 256x256 (slick may already do this).  Then just make black a transparent color when drawing.
cool story, bro

daniel_nieto

thanks for the replies (specially ouattwtym, he made me came up with the solution) I managed to get this working, let me tell you what i did, maybe someone has the same issue, i just changed the values in glTexCoord2f,
let me explain, i just divided the size of the actual image by the size of the texture loaded and assigned it to glTexCoord2f, when it is necessary instead of value 1. if it's hard to understand i'll put as example my actual case:

  GL11.glBindTexture(GL11.GL_TEXTURE_2D,texture.getTextureID());
		GL11.glBegin(GL11.GL_QUADS);
			GL11.glTexCoord2f(0,0);
			GL11.glVertex2f(100,100);
			GL11.glTexCoord2f(1,0);
			GL11.glVertex2f(100+texture.getTextureWidth(),100);
			GL11.glTexCoord2f(1,1);
			GL11.glVertex2f(100+texture.getTextureWidth(),100+texture.getTextureHeight());
			GL11.glTexCoord2f(0,1);
			GL11.glVertex2f(100,100+texture.getTextureHeight());
		GL11.glEnd();


With that code, the 256x256 loaded texture was being mapped onto my 200x200 quad, and the result is as you can see in the picture i uploaded on my previous post, it shrinks to fit the quad... so what i discovered is that the parameters on GL11.glTexCoord2f are (i believe) the number of times the texture is gonna be repeated or some like that... (i came up with this conclusion when i wrote 2's instead of 1's in GL11.glTexCoord2f, and this made texture appear 4 times) [PLEASE CORRECT ME IF IM WRONG!!!] ::)....

So now im gonna explain the solution itself:  as the texture is bigger than the quad i dont want to be drawn not even 1 time, less than it, so it fits the quad, i just divided the size of my quad by the size of the texture:

GL11.glBindTexture(GL11.GL_TEXTURE_2D,texture.getTextureID());
		GL11.glBegin(GL11.GL_QUADS);
			GL11.glTexCoord2f(0,0);
			GL11.glVertex2f(100,100);
			GL11.glTexCoord2f(imageWidth/textureWidth,0);
			GL11.glVertex2f(100+texture.getTextureWidth(),100);
			GL11.glTexCoord2f(imageWidth/textureWidth,imageHeight/textureHeight);
			GL11.glVertex2f(100+texture.getTextureWidth(),100+texture.getTextureHeight());
			GL11.glTexCoord2f(0,imageHeight/textureHeight);
			GL11.glVertex2f(100,100+texture.getTextureHeight());
		GL11.glEnd();


Hope this helps someone!

ouattwtym

I've just learnt that, in OpenGL-world, textures always measure 1.0 by 1.0. I suggested that you "paint your quad using only to top corner of your texture", though I didn't know how, and by drawing imageWidth/textureWidth by imageHeight/textureHeight you've done exactly that as these fractions will come in at less than 1.0 describing exactly the corner that you need. Very neat! :D :) :)