简体   繁体   中英

Android OpenGL ES texture mapping/drawing problem - skewed images

I have a problem with texture mapping in Android using OpenGL. Basically the problem is, that most of the Squares (my class I use for drawing 2 triangles) are drawn properly, that is the textures on them are exactly as they should be and everything is sweet. But some Squares are drawn a bit weirdly. Basically every next horizontal line starting from the top gets drawn about 1 pixel shifted to the left. This is an example image: http://postimage.org/image/1la0mr99g/ and this is how it gets drawn (the button above is the one that is exactly the same, but different texture): http://postimage.org/image/1lafildpg/

This is the class that is responsible for drawing images to screen. I must also add, that once a Square gets created I keep using and would potentially remap some textures later, but this is not the case for the images that get drawn wrong (in fact some other images I've remapped textures for get drawn fine). So basically, by looking at the code I've no idea what could be going wrong, as most of the Squares get drawn properly, and there is no bug visible to me. Also, I actually have 2 buttons, and they are exactly the same sizes and their images are also the same size - but one of the gets drawn just fine, whereas the other gets 'skewed'. The code for creating those buttons is literally the same, so I'm totally at a loss at what is going wrong.

public class GLSquare {
private float width, height;
private FloatBuffer vertexBuffer;   // buffer holding the vertices
private float vertices[]; /* = {
         -1.0f, 1.0f,  0.0f,        // V1 - bottom left
         -1.0f, -1.0f,  0.0f,        // V2 - top left
         1.0f, 1.0f,  0.0f,        // V3 - bottom right
         1.0f,  -1.0f,  0.0f         // V4 - top right
};
*/
private FloatBuffer textureBuffer;  // buffer holding the texture coordinates
private float texture[] = {         
        // Mapping coordinates for the vertices
         0.0f, 1.0f,     // top left     (V2)
         0.0f, 0.0f,     // bottom left  (V1)
         1.0f, 1.0f,     // top right    (V4)
         1.0f, 0.0f      // bottom right (V3)
};

/** The texture pointer */
private int[] textures = new int[1];

public GLSquare(float width, float height) {
    this.width = width;
    this.height = height;
    vertices = new float[12];
    vertices[0] = -(width/2); vertices[1] = (height/2); vertices[2] = 0.0f;// V1 - bottom left
    vertices[3] = -(width/2); vertices[4] = -(height/2); vertices[5] =  0.0f;// V2 - top left
    vertices[6] = width/2; vertices[7] = (height/2); vertices[8] =  0.0f;// V3 - bottom right
    vertices[9] = width/2; vertices[10] = -(height/2); vertices[11] = 0.0f;// V4 - top right

    // a float has 4 bytes so we allocate for each coordinate 4 bytes
    ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuffer.order(ByteOrder.nativeOrder());

    // allocates the memory from the byte buffer
    vertexBuffer = byteBuffer.asFloatBuffer();

    // fill the vertexBuffer with the vertices
    vertexBuffer.put(vertices);

    // set the cursor position to the beginning of the buffer
    vertexBuffer.position(0);

    byteBuffer = ByteBuffer.allocateDirect(texture.length * 4);
    byteBuffer.order(ByteOrder.nativeOrder());
    textureBuffer = byteBuffer.asFloatBuffer();
    textureBuffer.put(texture);
    textureBuffer.position(0);
}
public float getWidth(){
    return width;
}
public float getHeight(){
    return height;
}
public void loadGLTexture(GL10 gl, Bitmap bitmap) {
    // Generate a texture pointer
    gl.glGenTextures(1, textures, 0);
    // Bind texture to array
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

    // create nearest filtered texture
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
    gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    // Use Android GLUtils to specify a two-dimensional texture image from our bitmap 
    GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

    // Clean up
    bitmap.recycle();
}   
public void draw(GL10 gl, float x, float y, float scaleX, float scaleY, float angle) {

    gl.glPushMatrix();

    // bind the previously generated texture
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);

    // Point to our buffers
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    // Set the face rotation
    gl.glFrontFace(GL10.GL_CW);

    // Point to our vertex buffer
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    //translate to the wanted x,y coord
    gl.glTranslatef(x, y, 0.0f);

    if(angle != 0.0f){
        gl.glRotatef(angle, 0.0f, 0.0f, 1.0f);  
    }       
    if(scaleX != 1.0f && scaleY != 1.0f){
        gl.glScalef(scaleX, scaleY, 0.0f);
    }       

    // Draw the vertices as triangle strip
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);

    //Disable the client state before leaving
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    gl.glPopMatrix();
}

}

It looks like an alignment problem. This is a bit surprising as I expected GLUtils.texImage2D was setting all parameters apropriately.

In C you would add

glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // correction, should be 1 

However it's quite easy to test if you're really running into an alignment problem: Make your image width a multiple of 8: With that size no matter what the alignment setting is, your image should always show correctly.

It could also be a wrong setting of ROW_LENGTH. You could try adding the two calls I pictured above (of course adding the proper namespaces, ie gl. and GL10.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM