Как заполнить каждую сторону куба различными текстурами на OpenGL ES 1.1? - PullRequest
10 голосов
/ 14 октября 2011

Пожалуйста, мне нужны учебники / примеры кода, как заполнить каждую сторону куба различными текстурами в OpenGL ES 1.1

Я нашел много уроков, но ни один из них не объясняет, как наложить разные текстуры на каждое лицо, и ни один из них не дает простых примеров кода, как это сделать.

Мой реальный код (из примеров), который рисует куб с одинаковой текстурой на каждой грани:

public class Cube {

/** The buffer holding the vertices */
private FloatBuffer vertexBuffer;
/** The buffer holding the texture coordinates */
private FloatBuffer textureBuffer;
/** The buffer holding the indices */
private ByteBuffer indexBuffer;

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

/** 
 * The initial vertex definition
 * 
 * Note that each face is defined, even
 * if indices are available, because
 * of the texturing we want to achieve 
 */ 
private float vertices[] = {
                    //Vertices according to faces
                    -1.0f, -1.0f, 1.0f, //Vertex 0
                    1.0f, -1.0f, 1.0f,  //v1
                    -1.0f, 1.0f, 1.0f,  //v2
                    1.0f, 1.0f, 1.0f,   //v3

                    1.0f, -1.0f, 1.0f,  //...
                    1.0f, -1.0f, -1.0f,         
                    1.0f, 1.0f, 1.0f,
                    1.0f, 1.0f, -1.0f,

                    1.0f, -1.0f, -1.0f,
                    -1.0f, -1.0f, -1.0f,            
                    1.0f, 1.0f, -1.0f,
                    -1.0f, 1.0f, -1.0f,

                    -1.0f, -1.0f, -1.0f,
                    -1.0f, -1.0f, 1.0f,         
                    -1.0f, 1.0f, -1.0f,
                    -1.0f, 1.0f, 1.0f,

                    -1.0f, -1.0f, -1.0f,
                    1.0f, -1.0f, -1.0f,         
                    -1.0f, -1.0f, 1.0f,
                    1.0f, -1.0f, 1.0f,

                    -1.0f, 1.0f, 1.0f,
                    1.0f, 1.0f, 1.0f,           
                    -1.0f, 1.0f, -1.0f,
                    1.0f, 1.0f, -1.0f,
                                        };

/** The initial texture coordinates (u, v) */   
private float texture[] = {         
                    //Mapping coordinates for the vertices
                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    1.0f, 1.0f, 

                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    1.0f, 1.0f,

                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    1.0f, 1.0f,

                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    1.0f, 1.0f,

                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    1.0f, 1.0f,

                    0.0f, 0.0f,
                    0.0f, 1.0f,
                    1.0f, 0.0f,
                    1.0f, 1.0f,

                                        };

/** The initial indices definition */   
private byte indices[] = {
                    //Faces definition
                    0,1,3, 0,3,2,           //Face front
                    4,5,7, 4,7,6,           //Face right
                    8,9,11, 8,11,10,        //... 
                    12,13,15, 12,15,14,     
                    16,17,19, 16,19,18,     
                    20,21,23, 20,23,22,     
                                        };

/**
 * The Cube constructor.
 * 
 * Initiate the buffers.
 */
public Cube() {
    //
    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

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

    //
    indexBuffer = ByteBuffer.allocateDirect(indices.length);
    indexBuffer.put(indices);
    indexBuffer.position(0);
}

/**
 * The object own drawing function.
 * Called from the renderer to redraw this instance
 * with possible changes in values.
 * 
 * @param gl - The GL Context
 */
public void draw(GL10 gl) {
    //Bind our only previously generated texture in this case
    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_CCW);

    //Enable the vertex and texture state
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    //Draw the vertices as triangles, based on the Index Buffer information
    gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);

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

/**
 * Load the textures
 * 
 * @param gl - The GL Context
 * @param context - The Activity context
 */
public void loadGLTexture(GL10 gl, Context context) {
    //Get the texture from the Android resource directory
    InputStream is = context.getResources().openRawResource(R.drawable.nehe);
    Bitmap bitmap = null;
    try {
        //BitmapFactory is an Android graphics utility for images
        bitmap = BitmapFactory.decodeStream(is);

    } finally {
        //Always clear and close
        try {
            is.close();
            is = null;
        } catch (IOException e) {
        }
    }

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

Ответы [ 2 ]

12 голосов
/ 14 октября 2011

Чтобы каждая грань имела различную текстуру, вам нужно визуализировать каждую грань куба индивидуально. Это означает, что для каждого лица вам нужно установить текстуру, а затем визуализировать лицо (используя glDrawArrays или glDrawElements). Так это будет выглядеть примерно так:

glEnable(GL_TEXTURE_2D);
...                        //maybe other state setup (like buffer bindings)
glVertexPointer(...);
glEnableClientState(GL_VERTEX_ARRAY);
...

for each(face of cube)
{
    glBindTexture(GL_TEXTURE_2D, <face_texture>);
    glDrawArrays(...) or glDrawElements(...);      //draw only a single face
}

glDisableClientState(GL_VERTEX_ARRAY);
...
glDisable(GL_TEXTURE_2D);
...                         //maybe other state cleanup

Вы не можете рендерить все грани куба за один вызов, если им нужны разные текстуры. Но, конечно, вы все равно можете хранить их все в одном массиве / VBO и просто использовать аргументы для glDrawArrays или glDrawElements, чтобы выбрать соответствующее лицо, как сделано выше.

Это довольно упрощенный пример псевдокода, и если все это звучит для вас очень чуждо, вам следует немного углубиться в OpenGL, а применение различных текстур к каждой грани куба - ваша наименьшая проблема.

РЕДАКТИРОВАТЬ: Хорошо, в соответствии с вашим обновленным кодом: Прежде всего, поскольку все позиции ваших вершин и texCoords хранятся в одних и тех же массивах, нам не нужно менять их для каждой грани. Кроме того, ваш индексный массив, кажется, содержит все грани, сохраненные в виде 6 индексов (2 треугольника) для каждой грани. Все это делает всю ситуацию очень легкой. Просто замените существующий вызов glDrawElements этим циклом по всем граням:

for(i=0; i<6; ++i)
{
    gl.glBindTexture(GL10.GL_TEXTURE_2D, texture[i]);   //use texture of ith face
    indexBuffer.position(6*i);                          //select ith face

    //draw 2 triangles making up this face
    gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_BYTE, indexBuffer);
}

Таким образом, для каждого лица мы выбираем его текстуру и рисуем только 2 треугольника, которые соответствуют этому лицу.

Как правило, при изучении примеров кода, а не книги или чего-либо подобного, вы должны по крайней мере убедиться, что понимаете значение каждой строки кода и каждого параметра функции. Только тогда вы сможете свободно адаптировать код к вашим потребностям и разрабатывать решения для проблем.

3 голосов
/ 10 января 2014

Мне удалось собрать воедино ответ христиан, для тех, кто заинтересован, вот полный код Cube.java:

public class Cube {

/** The buffer holding the vertices */
private FloatBuffer vertexBuffer;
/** The buffer holding the texture coordinates */
private FloatBuffer textureBuffer;
/** The buffer holding the indices */
private ByteBuffer indexBuffer;

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

/** Textures */
private int[] resourceIds = new int[]{
        R.drawable.img1,
        R.drawable.img2,
        R.drawable.img3,
        R.drawable.img4,
        R.drawable.img5,
        R.drawable.img6};

/**
 * The initial vertex definition
 *
 * Note that each face is defined, even
 * if indices are available, because
 * of the texturing we want to achieve
 */
private float vertices[] = {
        //Vertices according to faces
        -1.0f, -1.0f, 1.0f, //Vertex 0
        1.0f, -1.0f, 1.0f,  //v1
        -1.0f, 1.0f, 1.0f,  //v2
        1.0f, 1.0f, 1.0f,   //v3

        1.0f, -1.0f, 1.0f,  //...
        1.0f, -1.0f, -1.0f,
        1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, -1.0f,

        1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f, -1.0f,
        1.0f, 1.0f, -1.0f,
        -1.0f, 1.0f, -1.0f,

        -1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f, 1.0f,
        -1.0f, 1.0f, -1.0f,
        -1.0f, 1.0f, 1.0f,

        -1.0f, -1.0f, -1.0f,
        1.0f, -1.0f, -1.0f,
        -1.0f, -1.0f, 1.0f,
        1.0f, -1.0f, 1.0f,

        -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,
        -1.0f, 1.0f, -1.0f,
        1.0f, 1.0f, -1.0f,
};

/** The initial texture coordinates (u, v) */
private float texture[] = {
        //Mapping coordinates for the vertices

        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,

        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,

        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,

        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,

        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,

        0.0f, 1.0f,
        1.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,

};

/** The initial indices definition */
private byte indices[] = {
        //Faces definition
        0,1,3, 0,3,2,           //Face front
        4,5,7, 4,7,6,           //Face right
        8,9,11, 8,11,10,        //...
        12,13,15, 12,15,14,
        16,17,19, 16,19,18,
        20,21,23, 20,23,22,
};

/**
 * The Cube constructor.
 *
 * Initiate the buffers.
 */
public Cube() {
    //
    ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
    byteBuf.order(ByteOrder.nativeOrder());
    vertexBuffer = byteBuf.asFloatBuffer();
    vertexBuffer.put(vertices);
    vertexBuffer.position(0);

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

    //
    indexBuffer = ByteBuffer.allocateDirect(indices.length);
    indexBuffer.put(indices);
    indexBuffer.position(0);
}

/**
 * The object own drawing function.
 * Called from the renderer to redraw this instance
 * with possible changes in values.
 *
 * @param gl - The GL Context
 */
public void draw(GL10 gl) {

    //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_CCW);

    //Enable the vertex and texture state
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
    gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);

    for (int i=0;i<6;i++){
        //Bind our only previously generated texture in this case
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[i]);
        indexBuffer.position(6*i);
        //Draw the vertices as triangles, based on the Index Buffer information
        gl.glDrawElements(GL10.GL_TRIANGLES, 6, GL10.GL_UNSIGNED_BYTE, indexBuffer);
    }

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

/**
 * Load the textures
 *
 * @param gl - The GL Context
 * @param context - The Activity context
 */
public void loadGLTexture(GL10 gl, Context context) {

    //Generate a 6 texture pointer...
    gl.glGenTextures(6, textures, 0);

    Bitmap bitmap = null;

    for (int i=0;i<6;i++)
    {
        // Create a bitmap
        bitmap = BitmapFactory.decodeResource(context.getResources(), resourceIds[i]);

        //...and bind it to our array
        gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[i]);

        //Create Nearest Filtered Texture
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_NEAREST);

        //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 the Android GLUtils to specify a two-dimensional texture image from our bitmap
        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

        //Clean up
        bitmap = null;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...