Texture atlas bleeding w/mipmap

Hi guys,

I am working a 2D tile based side scroller and attempting to use a texture atlas as suggested by many here to avoid multiple texture bind calls.

I was able to fix bleeding using half pixel correction using GL_NEAREST filtering, but I need a fix when using mipmaps. My issue is that my atlas is tightly packed 32x32 but I want my main character to be scaled to 48x48. When scaled (either up or down) it looks horrible when using GL_NEAREST so I decided to use mipmaps (GL_LINEAR_MIPMAP_LINEAR) which looks great, but breaks my fix for bleeding. All of my textures are POT btw.

I have tried google but can’t seem to find a fix. My relevent code is below and I would appreciate any suggestions.

Texture Loader:


	public static Texture loadTexture(String pathToFile)
	{
		int width = 0;
		int height = 0;
		BufferedImage img;
		int[] pixels = null;
		int id = 0;
		ByteBuffer bb = null;
		InputStream is;
		
		try 
		{
			is = ResourceManager.class.getClassLoader().getResourceAsStream(pathToFile);
			img = ImageIO.read(is);
			width = img.getWidth();
			height = img.getHeight();
			pixels = img.getRGB(0, 0, width, height, null, 0, width);
			is.close();
			bb = BufferUtils.createByteBuffer((width * height) * 4);
			id = glGenTextures();
			
		} catch (IOException e) 
		{
			System.out.println(e.getMessage());
			System.exit(1);
		}
		
		for(int i=0; i<pixels.length; i++)
		{
			byte r = (byte) ((pixels[i] >> 16) & 0xFF);
			byte g = (byte) ((pixels[i] >> 8) & 0xFF);
			byte b = (byte) ((pixels[i]) & 0xFF);
			byte a = (byte) ((pixels[i] >> 24) & 0xFF);
			
			bb.put(r);
			bb.put(g);
			bb.put(b);
			bb.put(a);
		}
		
		bb.flip();
		
		glBindTexture(GL_TEXTURE_2D, id);
		
		glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
		glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bb);
		
		glBindTexture(GL_TEXTURE_2D, 0);
		
		return new Texture(id,width,height);
	}

SpriteSheet code:


public SpriteSheet(Texture texture, int tileSize)
	{
		this.texture = texture;
		this.tileSize = tileSize;
		
		// Figure out how many texture coordinates we will have
		
		rows = texture.getHeight() / tileSize;
		cols = texture.getWidth() / tileSize;
	
		// Initialize the float buffers
		
		textureCoordinates = new FloatBuffer[rows * cols];
		vertexData = BufferUtils.createFloatBuffer(8);
		vertexData.put(new float[] {0,0,tileSize,0,tileSize,tileSize,0,tileSize});
		vertexData.flip();
		
		// Calculate all the texture coordinates ahead of time
		
		for(int i=0; i<rows; i++)
		{
			for(int j=0; j<cols; j++)
			{
				float srcX = j * tileSize;
				float srcY = i * tileSize;
				float u = (srcX + 0.5f) / texture.getWidth();
				float v = (srcY + 0.5f) / texture.getHeight();
				float u2 = (srcX + tileSize) / texture.getWidth();
				float v2 = (srcY + tileSize) / texture.getHeight();
				
 				//displayPosX -= displayPosX%0.1f;
            			//displayPosY -= displayPosY%0.1f;
				textureCoordinates[i * cols + j] = BufferUtils.createFloatBuffer(8);
				textureCoordinates[i * cols + j].put(new float[] {u,v,u2,v,u2,v2,u,v2});
				textureCoordinates[i * cols + j].flip();
			}
		}
		
	}