png image blurry when loaded onto texture
Asked Answered
H

5

6

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 http://img685.imageshack.us/img685/9130/upload2.png

alt text http://img695.imageshack.us/img695/2424/upload1e.png

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);
Hamhung answered 27/4, 2010 at 18:59 Comment(4)
What's the size (# pixels high & wide) of the texture in the PNG file?Bib
It looks like it might be something to do with the scaling of the image. Does resizing it in the game window change the quality?Bib
every thing is the same size when the window is resized, because of my gluOrtho2DHamhung
I should check opengl definitions, but as far as I know you cannot guarantee it won't be resized with this code. My best bet is the final render phase will assume that your image is 'a little' too small for the target and it will try to resize based on the 1:1 and 1:4 mipmap.Advocate
R
4

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).

Rhianna answered 27/4, 2010 at 21:50 Comment(3)
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).Ascot
@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).Rhianna
It could also just be the video drivers. I've been working on an OpenGL powered 2D game and many ATI GPU's don't properly support NPOT textures. They appear fuzzy just as they do in the screenshot even though they're not being scaled. Basically, you have two options. Make the PNG POT dimensions or get a different GPU.Fruitcake
A
3

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).

Advocate answered 27/4, 2010 at 19:18 Comment(3)
Can't get any of these to make it any better :(Hamhung
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?Advocate
It was different but didn't look betterHamhung
D
2

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.

Disentitle answered 27/4, 2010 at 20:44 Comment(0)
A
1

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 ?

Ascot answered 27/4, 2010 at 19:55 Comment(2)
This is my create window code, which has the same variables CreateGLWindow("Star Racer",width,height)Hamhung
Actually, that's incorrect thinking. When you create a window, the client area is created to the size that you need. The frame is added afterward by Windows. So if he says that he created his window at 800x600, his client area is indeed 800x600. I don't know about Linux but I know that at least MacOS X and Windows are smart enough to manage that properly. To prove the point, a quick copy/paste into any image editor shows that the image he posted is 816x638. That would be 800x600 + the window frame.Fruitcake
T
0
  • 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.
Talanian answered 27/4, 2010 at 20:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.