2011-05-04 119 views
0

我在使用OpenGL的Android紋理映射中遇到問題。基本上問題是,大多數Squares(我的班級用於繪製2個三角形)繪製得當,即它們上的紋理完全按照它們的樣子繪製,一切都很美妙。 但是有些方格有點奇怪。基本上,從頂部開始的每一條下一條水平線都會畫出左移1個像素。 這是一個示例圖像: http://postimage.org/image/1la0mr99g/ ,這是它如何被繪製(上面的按鈕是一個是完全一樣的,但不同的紋理): http://postimage.org/image/1lafildpg/Android OpenGL ES紋理映射/繪圖問題 - 傾斜圖像

這是負責繪製的類圖像屏幕。我還必須補充一點,一旦創建了Square,我將繼續使用並稍後重新映射一些紋理,但是對於繪製錯誤的圖像來說並不是這樣(事實上,其他一些圖像我已經重新映射了紋理以便繪製得很好)。所以基本上,通過查看代碼,我不知道會出現什麼問題,因爲大多數方塊都可以正確繪製,並且沒有可見的錯誤。 此外,我實際上有2個按鈕,他們是完全相同的大小和他們的圖像也是相同的大小 - 但其中一個得到繪製得很好,而另一個得到'傾斜'。創建這些按鈕的代碼在字面上是相同的,所以我完全不知道出了什麼問題。

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(); 
} 

}

回答

3

它看起來像一個對齊問題。這有點令人驚訝,因爲我期望GLUtils.texImage2D正確設置所有參數。

在C你會增加

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

但是它很容易測試,如果你真的遇到了一個定位的問題:讓你的圖像寬度爲8的倍數:由於該尺寸不管是什麼對齊設置是,你的圖像應該始終顯示正確。

它也可能是錯誤的ROW_LENGTH設置。你可以嘗試添加我上面描述的兩個調用(當然,添加正確的名稱空間,即gl和GL10)。

+0

Hey datenwolf, 是的,我已經在OpenGL irc頻道上得到了答案。這是glPixelStorei方法,需要調用它才能工作。 它必須是 gl.glPixelStorei(GL10.GL_UNPACK_ALIGNMENT,1); 它的工作。 此外,第一種方法不起作用 - 因爲沒有值GL_UNPACK_ROW_LENGTH。 感謝您的幫助,希望如果有人有同樣的問題,他們會看到這一點。 現在我需要解決,爲什麼該應用程序在模擬器上運行,而不是在我的2個電話上運行...... Geez! – cloudjubei 2011-05-04 17:19:00

+0

@是的,對齊1是正確的,不是0,我的不好:P – datenwolf 2011-05-04 20:29:44

+0

我有一個不相干的問題。不過,這個解釋對我很有幫助。 「使圖像寬度爲8的倍數」。爲此+1。 – efeyc 2012-01-02 09:48:57