views:

246

answers:

5

I have created a png image in photoshop with transparencies that I have loaded into and OpenGL program. I have binded it to a texture and in the program the picture looks blurry and I'm not sure why.

alt text

alt text

Loading Code

// Texture loading object
nv::Image title;

// Return true on success
if(title.loadImageFromFile("test.png"))
{
    glGenTextures(1, &titleTex);
    glBindTexture(GL_TEXTURE_2D, titleTex);
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
    glTexImage2D(GL_TEXTURE_2D, 0, title.getInternalFormat(), title.getWidth(), title.getHeight(), 0, title.getFormat(), title.getType(), title.getLevel(0));
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f);
}

else
    MessageBox(NULL, "Failed to load texture", "End of the world", MB_OK | MB_ICONINFORMATION);

Display Code

glEnable(GL_TEXTURE_2D);    
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindTexture(GL_TEXTURE_2D, titleTex);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTranslatef(-800, 0, 0.0);
glColor3f(1,1,1);

glBegin(GL_QUADS);
    glTexCoord2f(0.0, 0.0); glVertex2f(0,0);
    glTexCoord2f(0.0, 1.0); glVertex2f(0,600);
    glTexCoord2f(1.0, 1.0); glVertex2f(1600,600);
    glTexCoord2f(1.0, 0.0); glVertex2f(1600,0);
glEnd();
glDisable(GL_BLEND);    
glDisable(GL_TEXTURE_2D);

EDIT: I don't think i'm stretching each pixel should be two in the co-ordinate system

int width=800, height=600;
int left = -400-(width-400);
int right = 400+(width-400);
int top = 400+(height-400);
int bottom = -400-(height-400);
gluOrtho2D(left,right,bottom,top);
+1  A: 

Why would you want to use mipmapping and anisotropic filtering for a static image on your start screen in the first place? It looks unlikely the image will be rotated (what anisotropic filtering is for) or has to be resized many times really fast (what mipmapping is for).

If the texture is being stretched: try using GL_NEAREST for your GL_MAG_FILTER, in this case it could give better results (GL_LINEAR is more accurate, but has a nature of blurring).

If the texture is minimized: same thing, try using GL_NEAREST_MIPMAP_NEAREST, or even better, try using no mipmaps and GL_NEAREST (or GL_LINEAR, whichever gives you the best result).

KillianDS
Can't get any of these to make it any better :(
Chris
You have absolutely no difference? For example, because of the blending I would suspect the white borders still to be 'ugly', but the text inside the boxes should be sharp. If none of this changes the image, I was probably wrong and your texture is not being resized. Did you try rendering it to a screen that is just a little too large (e.g. screen of (824x618)) and using GL_NEAREST for MAG?
KillianDS
It was different but didn't look better
Chris
+1  A: 

Here is an hypothesis:

Your window is 800x600 (and maybe your framebuffer too), but your client area is not, because of the window decoration on the sides.

So your frame-buffer gets resized when being blitted to the client area of your window. Can you check your window creation code ?

Bahbar
This is my create window code, which has the same variables CreateGLWindow("Star Racer",width,height)
Chris
A: 
  • Beware of exact size of the client area of your window. Double check it is what you expect it to be
  • Beware of pixel alignment rules. You might need to add 0.5 to your x/y coordinates to hit the pixel centers. Description for DirectX can be found here - OpenGL rules may be different, though.
Suma
+1  A: 

I'd suggest that you make the png have a resolution in a power of 2's. Ie 1024x512 and place the part you want to drawn in the upper left corner of it still in the resolution for the screen. Then rescale the texcoords to be 800.0/1024.0 and 600.0/512.0 to get the right part from the texture. I belive that what is going on is glTexImage2D can sometime handle width and height that are not a power of 2 but can then scale the input image thus filter it.

An example of handling this can be viewed here (a iPhone - OpenGLES - project that grabs a screen part non-power of 2 and draws that into a 512x512 texture and rescales the GL_TEXTURE matrix, line 123, instead of doing a manual rescale of the texcoords)

Here is another post mentioning this method.

epatel
+2  A: 

OpenGL will (normally) require that the texture itself have a size that's a power of 2, so what's (probably) happening is that your texture is being scaled to a size where the dimensions are a power of 2, then it's being scaled back to the original size -- in the process of being scaled twice, you're losing some quality.

You apparently just want to display your bitmap without any scaling, without wrapping it to the surface of another object, or anything like that (i.e., any of the things textures are intended for). That being the case, I'd just display it as a bitmap, not a texture (e.g. see glRasterPos2i and glBitmap).

Jerry Coffin
I'd be interested to know _which_ implementation does this. As far as I know, this is not compliant with GL. Either you support NPOT textures, and you're supposed to load them just fine, or you don't, and you're supposed to fail the glTexImage call. Also, glBitmap has this nasty side-effect of transferring the data on each call by default. Make sure to use a Buffer Object to avoid it (GL_PIXEL_UNPACK_BUFFER).
Bahbar
@Bahbar: note that not everything involved is part of OpenGL proper -- his `nv::Image::LoadImageFromFile` is entirely separate -- and my guess is that it's what's doing the initial conversion to a POT size (either initially, or in a conversion when you take what it loaded and use it as a texture).
Jerry Coffin
Ah, good call. Cheers
Bahbar