Texture filters in OpenGL bring a lot of troubles.
Here I will describe some of them. You are certainly going to meet these during your game development.
1. The NEAREST filter makes your graphics to look ugly as hell:
Well, actually when you keep your sprites unrotated and at the 100% scale it looks just perfect and the problem does not exist. But when you want to scale and rotate… Here is my example: the original scene has the size 800×480 pixels, so on the devices with 800×480 resolution it looks just perfect, except for the arrows broken by rotation (click on image):
The problems come when I run the game on devices with different screen resolutions. I’m using the “Fit-in” camera, which is fitting the image into the device screen while keeping the original aspect ratio. So, independently from the screen resolution, the scene camera nicely scales my game like this:
and here the NEAREST filter makes it ugly (click on image to see “stairs”):
Summary: the NEAREST filter is not good when you need:
- to scale the scene into the screen properly,
- to rotate sprites (arrows and game objects like airplanes and bombs),
- to do some zoom-ins/zoom-outs with your scene camera.
2. The LINEAR filter.
This one looks relatively fine, but it gives artifacts on sprites:
The problem arises from the very nature of using linear sampling. This is called “sprite bleeding” – when texture borders are damaged with jpeg noise from the neighborhood pixels. This well-known problem can be solved by using the Texture Packer. The packer will pad your textures with additional pixels, carefully pack images next to each other reducing bleeding between them, and use a power-of-two size for your texture region to minimize floating point inaccuracies.
Problem solved? No. Bad news. These all work only when you use textures with no transparent pixels. The artifacts still appear on the borders between alpha and non-alpha pixels inside your texture:
So this is what is going to happen with our airplanes:
What’s just happened? Let’s see. Our original PNG-texture consists of 2 parts (or “layers”):
- image data
- and alpha-mask
Together they form our texture:
When we scale the image using the LINEAR filter the “layers” get some floating-operations damage, which produces the border:
Summary: The LINEAR filter is better than NEAREST, but it has this well-known “border”-problem for scaling alpha pixels.
Solution? There is one. Awesome people from the http://blog.gemserk.com/ team were so tired of these filter problems, so they’ve made a tool. The tool properly bleeds the colors of the non-transparent pixels into the transparent ones, so when scaled borders look fine. Here how it works:
The method still doesn’t work for sprites with half-transparent pixels, but… who cares, this is not a common thing. Just ignore it. Source code of the tool is available here: https://github.com/gemserk/imageprocessing.
Now good news everyone! I’ve merged the gemserk’s source code with the available source code of the libGDX TexturePacker and here it is: TexturePackerGemserk.zip