0

我想尽可能简单地在立方体上制作多个纹理。立方体的每一侧都应该有不同的纹理(图片就像在 loadtexture 方法中加载的那样,android.png)。我的代码的一部分:

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 方法或对其进行编辑?考虑过不回收位图,这有帮助吗?

4

1 回答 1

0

Thera 有可能实现这一目标的方法。最直接的方法是加载所有纹理,然后在绘制每一侧之前绑定一个不同的纹理(所以你所缺少的只是glBindTexture在 each 之前glDrawArrays)。对于这种情况,您不需要多个纹理坐标缓冲区,总体而言,您甚至不需要多个顶点缓冲区。您可以创建 1 个方形缓冲区并使用每边的矩阵定位(旋转)它(+ 绑定正确的纹理)。

另一种方法是使用一个纹理,您可以通过它加载所有 6 个图像glTextureSubImage(所有图像都位于纹理的不同部分,没有重叠),然后为立方体的每一侧使用不同的纹理坐标。通过这样做,您可以为整个立方体创建一个顶点/纹理缓冲区,并且能够通过一次glDrawArrays调用来绘制它。尽管在您的特定情况下,这将不少于 4x6=24 个顶点。

正如您所说,您不了解纹理坐标数组。纹理坐标是与纹理上的相对位置相对应的坐标。也就是说,(0,0)是纹理(图像)的左上角,(1,1)是它的右下角。如果纹理上有 4 个图像,例如 2x2,并且您希望使用左下角的图像,您的纹理坐标将如下所示:

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

至于坐标值大于 1.0 或小于 .0 我相信它们可以用来夹住对象的某些部分或重复纹理(这两个是购买的可能的纹理参数,通常在加载纹理时设置) . 至于纹理坐标的数量,它应该至少与 in 中的最后一个参数glDrawArrays一样多,或者在使用时与最大索引+1 一样多glDrawElements。因此,对于您的特定情况,您只能拥有 1 个纹理坐标缓冲区,除非您在某个时候改变主意并希望其中一侧在其上具有旋转图像并通过更改纹理坐标来解决该问题。

于 2013-05-14T13:17:03.817 回答