Search code examples
cmacosopenglmipmaps

OpenGL billboard interpolation issue


I have a billboard quad with a texture mapped onto it.

This is basically some text with transparency.

The billboard floats forwards and backwards from the camera's perspective.

As the billboard moves away (and appears smaller) there is an flickering effect around the edges of the text where there is a stroke border on the actual texture.

I think this is because interpolation is needed as the image which is normally X pixels wide is now shown as only a % of X and some pixels need to be merged together. I guess it's doing nearest neighbour or something? Can anyone point me in the right direction for opengl settings to control this, I'm guessing there is some way of preventing this effect from happening by adjusting the method for how the texture is handled ?

I think its got something to do with:

GL_NEAREST_MIPMAP_NEAREST

but when i try setting this for the MIN filter and enabling mip mapping my texture becomes very blocky and blurred...

i've also tried:

GL_LINEAR_MIPMAP_LINEAR

which is apparently triliear filtering for the MIN filter but my image is very blurry when displayed. (looks like it is a very low res texture) any ideas what I'm doing wrong?

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // trilinear

glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

More code:

// Allocated memory needed for the bitmap context
spriteData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
// Uses the bitmap creation function provided by the Core Graphics framework. 
spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
// After you create the context, you can draw the sprite image to the context.
CGContextDrawImage(spriteContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), spriteImage);
// You don't need the context at this point, so you need to release it to avoid memory leaks.
CGContextRelease(spriteContext);

// Use OpenGL ES to generate a name for the texture.
glGenTextures(1, &spriteTexture[textureCount-1]); 

// Bind the texture name. 
glBindTexture(GL_TEXTURE_2D, spriteTexture[textureCount-1]);


glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);



// Specify a 2D texture image, providing the a pointer to the image data in memory
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
// Release the image data
free(spriteData);

The texture is 512 x 512.

Example of the blurryness when the MIN filter is used:

Blurry billboard

When just using GL_NEAREST for the min filter sharper but nasty bilinear and the flickering as mentioned above when animated as shrinking:

GL_NEAREST


Solution

  • If you were using glu, I would suggest that you try using gluBuild2DMipmaps to create the mipmaps and see how others do this.

    To avoid using glu functions, I sometimes look at Mesa's OpenGL implementation to get some ideas (I generally try to keep a lot of code in my own project.. and I share a lot of it between OpenGL, D3D, and other platforms). You can try looking at the source for the Mesa implementation (MesaLib) of gluBuild2DMipmaps to see how you could get a similar effect. It appears in MesaLib's mipmap.c, and you'll probably end up jumping to the implementation of bitmapBuild2DMipmaps.

    I can't guarantee that this will lead to good results, but it's an avenue to explore. For general debugging of what's happening, another thing you could try is to output your mipmap textures to files for external viewing. All this is of course after you've exhausted your options of randomly toggling flags and googling other peoples' code to see if you missed any state functions.