2013-05-13 80 views
0

我想盡可能簡單地製作多個立方體上的紋理。應該有一個不同的貼圖(像LoadTexture方法中加載的圖片,android.png)在立方體的每一側。我的部分代碼:Android中的不同紋理

public class Square2 { 

private FloatBuffer vertexBuffer; // buffer holding the vertices 
private FloatBuffer vertexBuffer2; // buffer holding the vertices 
[and so on for all 6 sides] 
private float vertices[] = { 
     -1.0f, -1.0f, -1.0f,  // V1 - bottom left 
     -1.0f, 1.0f, -1.0f,  // V2 - top left 
     1.0f, -1.0f, -1.0f,  // V3 - bottom right 
     1.0f, 1.0f, 1.0f   // V4 - top right 
}; 
private float vertices2[] = { 
     1.0f, -1.0f, -1.0f,  // V1 - bottom left 
     1.0f, 1.0f, -1.0f,  // V2 - top left 
     1.0f, -1.0f, 1.0f,  // V3 - bottom right 
     1.0f, 1.0f, 1.0f   // V4 - top right 
}; 
[for all 6 sides too] 

private FloatBuffer textureBuffer; // buffer holding the texture coordinates 
private FloatBuffer textureBuffer2; // buffer holding the texture coordinates 
[and so on for all 6 sides] 

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

private float texture2[] = {    
     // 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) 
}; 

[dont really understand the texture array, is one enough for all sides, even if i want different textures?] 

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

public Square2() { 
    // 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 byteBuffer2 = ByteBuffer.allocateDirect(vertices2.length * 4); 
    byteBuffer2.order(ByteOrder.nativeOrder()); 

    // allocates the memory from the byte buffer 
    vertexBuffer2 = byteBuffer2.asFloatBuffer(); 

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

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


    [and so on for all 6 sides] 


    byteBuffer = ByteBuffer.allocateDirect(texture.length * 4); 
    byteBuffer.order(ByteOrder.nativeOrder()); 
    textureBuffer = byteBuffer.asFloatBuffer(); 
    textureBuffer.put(texture); 
    textureBuffer.position(0); 

    [and so on] 
} 

/** 
* Load the texture for the square 
* @param gl 
* @param context 
*/ 
public void loadGLTexture(GL10 gl, Context context) { 
    // loading texture 
    Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), 
      R.drawable.android); 

    // generate one texture pointer 
    gl.glGenTextures(1, textures, 0); 

    // ...and bind it to our 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); 

    //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE 
      //gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT); 
      //gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT); 

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

/** The draw method for the square with the GL context */ 
public void draw(GL10 gl) { 
    // bind the previously generated texture 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]); 
    gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[1]); 

    // 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 buffer1 vorn 
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); 
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer); 

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

    //2 rechts 
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer2); 
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer2); 

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

    [and so on] 

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

不幸的是,這只是給了我所有方面相同的紋理。我怎樣才能在每一面做出不同的紋理?我必須多次調用loadtexture方法還是編輯它?想過不回收位圖,會有幫助嗎?

+0

你可能想編輯你的問題更多的細節。你到底想要達到什麼樣的目標?立方體兩側有不同的紋理?多紋理? – Grimmy 2013-05-13 10:33:22

+0

謝謝,只是做到了:)希望現在更清楚:) – Applecow 2013-05-13 11:11:09

回答

0

Thera是可能的方式來實現這一點。最簡單的方法是加載所有紋理,然後在繪製每一面之前綁定一個不同的紋理(因此,在缺失每個glDrawArrays之前缺少的是glBindTexture)。對於這種情況,您不需要多個紋理座標緩衝區,總體上甚至不需要多個頂點緩衝區。您可以創建1個方形緩衝區,並使用矩陣爲每一邊定位(旋轉)它(+綁定正確的紋理)。

另一種方法是使用單個紋理,您可以通過glTextureSubImage(全部位於紋理的不同部分,不重疊)加載所有6個圖像,然後對立方體的每一側使用不同的紋理座標。通過這樣做,您可以爲整個立方體創建單個頂點/紋理緩衝區,並且可以使用單個glDrawArrays調用來繪製它。雖然在你的具體情況下不會少於4×6 = 24個頂點。

正如您所說的,您不瞭解紋理座標數組。紋理座標是對應於紋理上的相對位置的座標。那就是,(0,0)是紋理(圖像)的左上角部分,(1,1)是它的右下角部分。如果紋理對其有4張圖片爲2×2,你會例如要使用的左下角,您的紋理座標應該是這樣的:

private float texture[] = {   
     0.0f, 1.0f, 
     0.0f, .5f, 
     .5f, 1.0f, 
     .5f, 0.5f 
}; 

至於是更大然後1.0或更小的座標值那麼.0我相信他們可以用ether來夾住物體的某些部分或者重複紋理(這些2是買來紋理的可能參數,通常在加載紋理時設置)。至於紋理座標的數量,它應該至少與glDrawArrays中的最後一個參數一樣多,或者當使用glDrawElements時最多可以是最大的索引+1。因此,對於您的特定情況,您只能擁有1個紋理座標緩衝區,除非您在某些時候會改變主意並希望其中一邊旋轉圖像並通過更改紋理座標來解決該問題。