Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android OpenGL - ES Texture bleeding

I am writing a small app that at the moment generates a random map of textures.

I am drawing this map as a 10 x 15 group of "quads" which are infact all triangle strips. I use the "map" to grab an int which I then take as the location of the texture for this square in the textureAtlas. so for example 0 is the bottom left "tile". The atlas is 128 x 128 and split into 32 pixel tiles.

However I seem to be getting some odd artifacts where the texture from the one tile is creeping in to the next tile. I wondered if it was the image itself but as far as I can tell the pixels are exactly where they should be. I then looked at the texture coords I was specifying but they all look exact (0.0, 0.25, 0.5, 0.75, 1.0 - splitting it into the 4 rows and columns I would expect).

The odd thing is if I run it on the emulator I do not get any artifacts.

Is there a setting I am missing which would cause bleeding of 1 pixel? It seemed to only be vertical too - this could be related to on the phone I am "stretching" the image in that direction as the phone's screen is larger than normal in that direction.

I load the texture like so:

//Get a new ID
    int id = newTextureID(gl);

    //We will need to flip the texture vertically
    Matrix flip = new Matrix();
    flip.postScale(1f, -1f);

    //Load up and flip the texture
    Bitmap temp = BitmapFactory.decodeResource(context.getResources(), resource);

    //Store the widths for the texturemap
    int width = temp.getWidth();
    int height = temp.getHeight();
    Bitmap bmp = Bitmap.createBitmap(temp, 0, 0, width, height, flip, true);
    temp.recycle();

    //Bind
    gl.glBindTexture(GL10.GL_TEXTURE_2D, id);

    //Set params
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR);

    //Push onto the GPU
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0);

    TextureAtlas atlas = new TextureAtlas(id, width, height, tileSize);
    return atlas;

I then render it like so:

gl.glBindTexture(GL10.GL_TEXTURE_2D, currentAtlas.textureID);
    //Enable the vertices buffer for writing and to be used during our rendering
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    //Specify the location and data format of an array of vertex coordinates to use
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);

    //Enable the texture buffer
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
    gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_SHORT, indexBuffer);

I would take a picture, but I am unsure how to get a screen cap from the phone...

If anyone knows of how I can capture the current frame and perhaps put it out into a file I will do that if it helps explain what is going on!

Look forward to your response.

Edit: Here is a screencap - note I run the app in landscape but cap is in portrait. Also excuse the horrible textures :D they were merely a place holder / messing around.

ScreenCap

like image 722
iexus Avatar asked Oct 18 '10 18:10

iexus


1 Answers

Well, after speaking to a friend I managed to solve this little problem.

It turns out that if you wish to have exact pixel perfect textures you have to specify the edge of the texture to be halfway into the pixel.

To do this I simply added half a pixel or subtracted half a pixel to the measurement for the texture coords.

Like so:

//Top Left
            textureCoords[textPlace] = xAdjust*currentAtlas.texSpaceWidth + currentAtlas.halfPixelAdjust;        textPlace++;
            textureCoords[textPlace] = (yAdjust+1)*currentAtlas.texSpaceHeight - currentAtlas.halfPixelAdjust;    textPlace++;

This was simply calculated when loading the texture atlas:

(float)(0.5 * ((1.0f / numberOfTilesInAtlasRow) / pixelsPerTile));

Although if the height was different to the width of each tile (which could happen) you would need to calculate them individually.

This has solved all the artifacts so I can continue on. Hope it helps someone else!

like image 113
iexus Avatar answered Nov 02 '22 20:11

iexus