OpenGL ES - 纹理映射8个顶点立方体的所有面?

时间:2010-05-18 02:32:21

标签: android opengl-es

使用Android模拟器完成一些OpenGL-ES教程。我已经完成了纹理映射,并且在映射到多维数据集时遇到了一些麻烦。是否可以将纹理映射到具有8个顶点和12个三角形的立方体的所有面,如下所述?

// Use half as we are going for a 0,0,0 centre.
    width  /= 2;
    height /= 2;
    depth  /= 2;

    float vertices[] = { -width, -height, depth, // 0
                          width, -height, depth, // 1
                          width,  height, depth, // 2
                         -width,  height, depth, // 3
                         -width, -height, -depth, // 4
                          width, -height, -depth, // 5
                          width,  height, -depth, // 6
                         -width,  height, -depth, // 7
    };

    short indices[] = { 
            // Front
            0,1,2,
            0,2,3,
            // Back
            5,4,7,
            5,7,6,
            // Left
            4,0,3,
            4,3,7,
            // Right
            1,5,6,
            1,6,2,
            // Top
            3,2,6,
            3,6,7,
            // Bottom
            4,5,1,
            4,1,0,
    };

   float texCoords[] = {
        1.0f, 1.0f,
        0.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,

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

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

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

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

        1.0f, 1.0f,
        0.0f, 1.0f,
        0.0f, 0.0f,
        1.0f, 0.0f,
    };

我已经让正面和背面正常工作,但是,没有其他面部正在显示纹理。

alt text http://www.freeimagehosting.net/uploads/60d292613d.jpg

绘图代码

public void draw(GL10 gl) {
    // Counter-clockwise winding.
    gl.glFrontFace(GL10.GL_CCW);

    // Enable face culling.
    gl.glEnable(GL10.GL_CULL_FACE);

    // What faces to remove with the face culling.
    gl.glCullFace(GL10.GL_BACK);

    // Enabled the vertices buffer for writing and to be used during
    // rendering.
    gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

    // Specifies the location and data format of an array of vertex
    // coordinates to use when rendering.
    gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);

    if (normalsBuffer != null) {
        // Enabled the normal buffer for writing and to be used during rendering.
        gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);

        // Specifies the location and data format of an array of normals to use when rendering.
        gl.glNormalPointer(GL10.GL_FLOAT, 0, normalsBuffer);
    }

    // Set flat color
    gl.glColor4f(rgba[0], rgba[1], rgba[2], rgba[3]);

    // Smooth color
    if ( colorBuffer != null ) {
        // Enable the color array buffer to be used during rendering.
        gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
        // Point out the where the color buffer is.
        gl.glColorPointer(4, GL10.GL_FLOAT, 0, colorBuffer);
    }

    // Use textures?
    if ( textureBuffer != null) {
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
        gl.glEnable(GL10.GL_TEXTURE_2D);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
    }

    // Translation and rotation before drawing
    gl.glTranslatef(x, y, z);
    gl.glRotatef(rx, 1, 0, 0);
    gl.glRotatef(ry, 0, 1, 0);
    gl.glRotatef(rz, 0, 0, 1);

    gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices, GL10.GL_UNSIGNED_SHORT, indicesBuffer);

    // Disable the vertices buffer.
    gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
    gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);
    gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

    // Disable face culling.
    gl.glDisable(GL10.GL_CULL_FACE);
}

2 个答案:

答案 0 :(得分:6)

你必须使用24个顶点。在OpenGL中,顶点不仅仅是位置,它是所有顶点属性的集合。使用相同的索引访问每个顶点数组。

臭名昭着的多维数据集示例几乎每个人都认为在开始使用OpenGL时效率低下,但在现实世界中,更复杂的模型中,重复程度非常低。

答案 1 :(得分:0)

我“仅”将GLES20TriangleRenderer.java文件修改为SDK示例BasicGLSurfaceView,编译并在两个Android设备,Android手机和Nexus 7上进行测试,这在两个设备上运行良好:)

/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.

   Modified by YLP (06 January 2014) for to handle a rotated texture mapped cube

 */

package com.example.android.basicglsurfaceview;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLUtils;
import android.opengl.Matrix;
import android.os.SystemClock;
import android.util.Log;

class GLES20TriangleRenderer implements GLSurfaceView.Renderer {

    public GLES20TriangleRenderer(Context context) {
        mContext = context;

        // mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
        // mTriangleVertices.put(mTriangleVerticesData).position(0);

        mTriangleVertices = ByteBuffer.allocateDirect(cubeVerticesStrip.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mTriangleVertices.put(cubeVerticesStrip).position(0);

        mTriangleTexcoords = ByteBuffer.allocateDirect(cubeTexCoordsStrip.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer();
        mTriangleTexcoords.put(cubeTexCoordsStrip).position(0);

    }

    public void onDrawFrame(GL10 glUnused) {
        // Ignore the passed-in GL10 interface, and use the GLES20
        // class's static methods instead.
        GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
        GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

        GLES20.glEnable( GLES20.GL_DEPTH_TEST );
        GLES20.glDepthFunc( GLES20.GL_LEQUAL );
        GLES20.glDepthMask( true );

        GLES20.glUseProgram(mProgram);
        checkGlError("glUseProgram");

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);

        // mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET);
        // GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false,
        //        TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
        // checkGlError("glVertexAttribPointer maPosition");

        // mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET);
        // GLES20.glEnableVertexAttribArray(maPositionHandle);
        // checkGlError("glEnableVertexAttribArray maPositionHandle");

        // GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,
        //         TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
        // checkGlError("glVertexAttribPointer maTextureHandle");
        // GLES20.glEnableVertexAttribArray(maTextureHandle);
        // checkGlError("glEnableVertexAttribArray maTextureHandle");

        // From http://www.endodigital.com/opengl-es-2-0-on-the-iphone/part-fourteen-creating-the-cube
        // (but slighty modified)
        mTriangleVertices.position(0);
        // GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
           GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 0, mTriangleVertices);
        GLES20.glEnableVertexAttribArray(maPositionHandle);

        mTriangleTexcoords.position(0);
        // GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices);
           GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 0, mTriangleTexcoords);
        GLES20.glEnableVertexAttribArray(maTextureHandle);

        long time = SystemClock.uptimeMillis() % 4000L;
        float angle = 0.090f * ((int) time);
        float scale = 0.7f;

        Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f);

        // YLP : add others movements cycles
        Matrix.rotateM(mMMatrix, 0, angle, 1.0f, 0.0f, 0.0f );
        // Matrix.rotateM(mMMatrix, 0, angle, 0.0f, 1.0f, 0.0f );
        // float scale = (float)( Math.abs( Math.sin( ((float)time) * (6.28f/4000.0f) ) ));
        Matrix.scaleM(mMMatrix, 0, scale, scale, scale);


        Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);

        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);

        // Somes tests with only somes triangles
        // GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); // worked initialy but only one triangle
        // GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); // worked initialy but only two triangles
        // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); // GL_QUADS does not exist in GL 2.0  :(
        // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 8); // GL_QUADS does not exist in GL 2.0  :(

        // Draw the cube
        // TODO : make only one glDraWArrays() call instead one per face
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 4, 4);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 8, 4);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 12, 4);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 16, 4);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 20, 4);

        checkGlError("glDrawArrays");
    }

    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
        // Ignore the passed-in GL10 interface, and use the GLES20
        // class's static methods instead.
        GLES20.glViewport(0, 0, width, height);
        float ratio = (float) width / height;
        Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
    }

    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
        // Ignore the passed-in GL10 interface, and use the GLES20
        // class's static methods instead.
        mProgram = createProgram(mVertexShader, mFragmentShader);
        if (mProgram == 0) {
            return;
        }
        maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
        checkGlError("glGetAttribLocation aPosition");
        if (maPositionHandle == -1) {
            throw new RuntimeException("Could not get attrib location for aPosition");
        }
        maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord");
        checkGlError("glGetAttribLocation aTextureCoord");
        if (maTextureHandle == -1) {
            throw new RuntimeException("Could not get attrib location for aTextureCoord");
        }

        muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
        checkGlError("glGetUniformLocation uMVPMatrix");
        if (muMVPMatrixHandle == -1) {
            throw new RuntimeException("Could not get attrib location for uMVPMatrix");
        }

        /*
         * Create our texture. This has to be done each time the
         * surface is created.
         */

        int[] textures = new int[1];
        GLES20.glGenTextures(1, textures, 0);

        mTextureID = textures[0];
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID);

        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
                GLES20.GL_NEAREST);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MAG_FILTER,
                GLES20.GL_LINEAR);

        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,
                GLES20.GL_REPEAT);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,
                GLES20.GL_REPEAT);

        InputStream is = mContext.getResources()
            .openRawResource(R.raw.robot);
        Bitmap bitmap;
        try {
            bitmap = BitmapFactory.decodeStream(is);
        } finally {
            try {
                is.close();
            } catch(IOException e) {
                // Ignore.
            }
        }

        GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
        bitmap.recycle();

        Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
    }

    private int loadShader(int shaderType, String source) {
        int shader = GLES20.glCreateShader(shaderType);
        if (shader != 0) {
            GLES20.glShaderSource(shader, source);
            GLES20.glCompileShader(shader);
            int[] compiled = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
            if (compiled[0] == 0) {
                Log.e(TAG, "Could not compile shader " + shaderType + ":");
                Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
        }
        return shader;
    }

    private int createProgram(String vertexSource, String fragmentSource) {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (vertexShader == 0) {
            return 0;
        }

        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (pixelShader == 0) {
            return 0;
        }

        int program = GLES20.glCreateProgram();
        if (program != 0) {
            GLES20.glAttachShader(program, vertexShader);
            checkGlError("glAttachShader");
            GLES20.glAttachShader(program, pixelShader);
            checkGlError("glAttachShader");
            GLES20.glLinkProgram(program);
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] != GLES20.GL_TRUE) {
                Log.e(TAG, "Could not link program: ");
                Log.e(TAG, GLES20.glGetProgramInfoLog(program));
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;
    }

    private void checkGlError(String op) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            Log.e(TAG, op + ": glError " + error);
            throw new RuntimeException(op + ": glError " + error);
        }
    }

    private static final int FLOAT_SIZE_BYTES = 4;
    private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
    private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0;
    private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
    private static final int TRIANGLE_TEXCOORDS_DATA_STRIDE_BYTES = 2 * FLOAT_SIZE_BYTES;

    private final float[] mTriangleVerticesData =
    {
            // X, Y, Z, U, V

           // initial triangle from the source
           // -1.0f,   -0.5f,          0,  -0.5f,   0.0f,
           //  1.0f,   -0.5f,          0,   1.5f,  -0.0f,
           // 0.0f,    1.11803399f,   0,   0.5f,   1.61803399f,

            // YLP : transform this to two triangles for to have a quad
            // -1, -1, 0,    0, 0,
            // 1, -1, 0,    1, 0,
            // -1,  1, 0,    0, 1,
            // 1,  1, 0,    1, 1,
            // -1,  1, 0,    0, 1,
            // 1, -1, 0,    1, 0

            // YLP :  use two quads with GL_TRIANGLE_STRIP
            // Don't work because this make one accordeon effect :(
            -1, -1, -1,    0, 0,
             1, -1, -1,    1, 0,
            -1,  1, -1,    0, 1,
             1,  1, -1,    1, 1,
            -1, -1,  1,    0, 0,
             1, -1,  1,    1, 0,
            -1,  1,  1,    0, 1,
             1,  1,  1,    1, 1,
    };

    // From http://www.endodigital.com/opengl-es-2-0-on-the-iphone/part-fourteen-creating-the-cube/
    // (only moodify "static const GLfloat" to "private final float" on it)
    private final float cubeVerticesStrip[] = {
            // Front face
            -1,-1,1, 1,-1,1, -1,1,1, 1,1,1,
            // Right face
            1,-1,1, 1,-1,-1, 1,1,1, 1,1,-1,
            // Back face
            1,-1,-1, -1,-1,-1, 1,1,-1, -1,1,-1,
            // Left face
            -1,-1,-1, -1,-1,1, -1,1,-1, -1,1,1,
            // Bottom face
            -1,-1,-1, 1,-1,-1, -1,-1,1, 1,-1,1,
            // Top face
            -1,1,1, 1,1,1, -1,1,-1, 1,1,-1

    };

    private final float cubeTexCoordsStrip[] = {
            // Front face
            0,0, 1,0, 0,1, 1,1,
            // Right face
            0,0, 1,0, 0,1, 1,1,
            // Back face
            0,0, 1,0, 0,1, 1,1,
            // Left face
            0,0, 1,0, 0,1, 1,1,
            // Bottom face
            0,0, 1,0, 0,1, 1,1,
            // Top face
            0,0, 1,0, 0,1, 1,1
    };

    private FloatBuffer mTriangleVertices;
    private FloatBuffer mTriangleTexcoords;

    private final String mVertexShader =
        "uniform mat4 uMVPMatrix;\n" +
        "attribute vec4 aPosition;\n" +
        "attribute vec2 aTextureCoord;\n" +
        "varying vec2 vTextureCoord;\n" +
        "void main() {\n" +
        "  gl_Position = uMVPMatrix * aPosition;\n" +
        "  vTextureCoord = aTextureCoord;\n" +
        "}\n";

    private final String mFragmentShader =
        "precision mediump float;\n" +
        "varying vec2 vTextureCoord;\n" +
        "uniform sampler2D sTexture;\n" +
        "void main() {\n" +
        "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
        "}\n";

    private float[] mMVPMatrix = new float[16];
    private float[] mProjMatrix = new float[16];
    private float[] mMMatrix = new float[16];
    private float[] mVMatrix = new float[16];

    private float[] mMMatrix2 = new float[16];

    private int mProgram;
    private int mTextureID;
    private int muMVPMatrixHandle;
    private int maPositionHandle;
    private int maTextureHandle;

    private Context mContext;
    private static String TAG = "GLES20TriangleRenderer";
}

/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. Modified by YLP (06 January 2014) for to handle a rotated texture mapped cube */ package com.example.android.basicglsurfaceview; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.GLUtils; import android.opengl.Matrix; import android.os.SystemClock; import android.util.Log; class GLES20TriangleRenderer implements GLSurfaceView.Renderer { public GLES20TriangleRenderer(Context context) { mContext = context; // mTriangleVertices = ByteBuffer.allocateDirect(mTriangleVerticesData.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); // mTriangleVertices.put(mTriangleVerticesData).position(0); mTriangleVertices = ByteBuffer.allocateDirect(cubeVerticesStrip.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); mTriangleVertices.put(cubeVerticesStrip).position(0); mTriangleTexcoords = ByteBuffer.allocateDirect(cubeTexCoordsStrip.length * FLOAT_SIZE_BYTES).order(ByteOrder.nativeOrder()).asFloatBuffer(); mTriangleTexcoords.put(cubeTexCoordsStrip).position(0); } public void onDrawFrame(GL10 glUnused) { // Ignore the passed-in GL10 interface, and use the GLES20 // class's static methods instead. GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1.0f); GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT); GLES20.glEnable( GLES20.GL_DEPTH_TEST ); GLES20.glDepthFunc( GLES20.GL_LEQUAL ); GLES20.glDepthMask( true ); GLES20.glUseProgram(mProgram); checkGlError("glUseProgram"); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID); // mTriangleVertices.position(TRIANGLE_VERTICES_DATA_POS_OFFSET); // GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, // TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); // checkGlError("glVertexAttribPointer maPosition"); // mTriangleVertices.position(TRIANGLE_VERTICES_DATA_UV_OFFSET); // GLES20.glEnableVertexAttribArray(maPositionHandle); // checkGlError("glEnableVertexAttribArray maPositionHandle"); // GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, // TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); // checkGlError("glVertexAttribPointer maTextureHandle"); // GLES20.glEnableVertexAttribArray(maTextureHandle); // checkGlError("glEnableVertexAttribArray maTextureHandle"); // From http://www.endodigital.com/opengl-es-2-0-on-the-iphone/part-fourteen-creating-the-cube // (but slighty modified) mTriangleVertices.position(0); // GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 0, mTriangleVertices); GLES20.glEnableVertexAttribArray(maPositionHandle); mTriangleTexcoords.position(0); // GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false,TRIANGLE_VERTICES_DATA_STRIDE_BYTES, mTriangleVertices); GLES20.glVertexAttribPointer(maTextureHandle, 2, GLES20.GL_FLOAT, false, 0, mTriangleTexcoords); GLES20.glEnableVertexAttribArray(maTextureHandle); long time = SystemClock.uptimeMillis() % 4000L; float angle = 0.090f * ((int) time); float scale = 0.7f; Matrix.setRotateM(mMMatrix, 0, angle, 0, 0, 1.0f); // YLP : add others movements cycles Matrix.rotateM(mMMatrix, 0, angle, 1.0f, 0.0f, 0.0f ); // Matrix.rotateM(mMMatrix, 0, angle, 0.0f, 1.0f, 0.0f ); // float scale = (float)( Math.abs( Math.sin( ((float)time) * (6.28f/4000.0f) ) )); Matrix.scaleM(mMMatrix, 0, scale, scale, scale); Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0); Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0); GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0); // Somes tests with only somes triangles // GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3); // worked initialy but only one triangle // GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6); // worked initialy but only two triangles // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); // GL_QUADS does not exist in GL 2.0 :( // GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 8); // GL_QUADS does not exist in GL 2.0 :( // Draw the cube // TODO : make only one glDraWArrays() call instead one per face GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 4, 4); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 8, 4); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 12, 4); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 16, 4); GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 20, 4); checkGlError("glDrawArrays"); } public void onSurfaceChanged(GL10 glUnused, int width, int height) { // Ignore the passed-in GL10 interface, and use the GLES20 // class's static methods instead. GLES20.glViewport(0, 0, width, height); float ratio = (float) width / height; Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7); } public void onSurfaceCreated(GL10 glUnused, EGLConfig config) { // Ignore the passed-in GL10 interface, and use the GLES20 // class's static methods instead. mProgram = createProgram(mVertexShader, mFragmentShader); if (mProgram == 0) { return; } maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition"); checkGlError("glGetAttribLocation aPosition"); if (maPositionHandle == -1) { throw new RuntimeException("Could not get attrib location for aPosition"); } maTextureHandle = GLES20.glGetAttribLocation(mProgram, "aTextureCoord"); checkGlError("glGetAttribLocation aTextureCoord"); if (maTextureHandle == -1) { throw new RuntimeException("Could not get attrib location for aTextureCoord"); } muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); checkGlError("glGetUniformLocation uMVPMatrix"); if (muMVPMatrixHandle == -1) { throw new RuntimeException("Could not get attrib location for uMVPMatrix"); } /* * Create our texture. This has to be done each time the * surface is created. */ int[] textures = new int[1]; GLES20.glGenTextures(1, textures, 0); mTextureID = textures[0]; GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureID); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT); InputStream is = mContext.getResources() .openRawResource(R.raw.robot); Bitmap bitmap; try { bitmap = BitmapFactory.decodeStream(is); } finally { try { is.close(); } catch(IOException e) { // Ignore. } } GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); Matrix.setLookAtM(mVMatrix, 0, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f); } private int loadShader(int shaderType, String source) { int shader = GLES20.glCreateShader(shaderType); if (shader != 0) { GLES20.glShaderSource(shader, source); GLES20.glCompileShader(shader); int[] compiled = new int[1]; GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0); if (compiled[0] == 0) { Log.e(TAG, "Could not compile shader " + shaderType + ":"); Log.e(TAG, GLES20.glGetShaderInfoLog(shader)); GLES20.glDeleteShader(shader); shader = 0; } } return shader; } private int createProgram(String vertexSource, String fragmentSource) { int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource); if (vertexShader == 0) { return 0; } int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource); if (pixelShader == 0) { return 0; } int program = GLES20.glCreateProgram(); if (program != 0) { GLES20.glAttachShader(program, vertexShader); checkGlError("glAttachShader"); GLES20.glAttachShader(program, pixelShader); checkGlError("glAttachShader"); GLES20.glLinkProgram(program); int[] linkStatus = new int[1]; GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0); if (linkStatus[0] != GLES20.GL_TRUE) { Log.e(TAG, "Could not link program: "); Log.e(TAG, GLES20.glGetProgramInfoLog(program)); GLES20.glDeleteProgram(program); program = 0; } } return program; } private void checkGlError(String op) { int error; while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) { Log.e(TAG, op + ": glError " + error); throw new RuntimeException(op + ": glError " + error); } } private static final int FLOAT_SIZE_BYTES = 4; private static final int TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; private static final int TRIANGLE_VERTICES_DATA_POS_OFFSET = 0; private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3; private static final int TRIANGLE_TEXCOORDS_DATA_STRIDE_BYTES = 2 * FLOAT_SIZE_BYTES; private final float[] mTriangleVerticesData = { // X, Y, Z, U, V // initial triangle from the source // -1.0f, -0.5f, 0, -0.5f, 0.0f, // 1.0f, -0.5f, 0, 1.5f, -0.0f, // 0.0f, 1.11803399f, 0, 0.5f, 1.61803399f, // YLP : transform this to two triangles for to have a quad // -1, -1, 0, 0, 0, // 1, -1, 0, 1, 0, // -1, 1, 0, 0, 1, // 1, 1, 0, 1, 1, // -1, 1, 0, 0, 1, // 1, -1, 0, 1, 0 // YLP : use two quads with GL_TRIANGLE_STRIP // Don't work because this make one accordeon effect :( -1, -1, -1, 0, 0, 1, -1, -1, 1, 0, -1, 1, -1, 0, 1, 1, 1, -1, 1, 1, -1, -1, 1, 0, 0, 1, -1, 1, 1, 0, -1, 1, 1, 0, 1, 1, 1, 1, 1, 1, }; // From http://www.endodigital.com/opengl-es-2-0-on-the-iphone/part-fourteen-creating-the-cube/ // (only moodify "static const GLfloat" to "private final float" on it) private final float cubeVerticesStrip[] = { // Front face -1,-1,1, 1,-1,1, -1,1,1, 1,1,1, // Right face 1,-1,1, 1,-1,-1, 1,1,1, 1,1,-1, // Back face 1,-1,-1, -1,-1,-1, 1,1,-1, -1,1,-1, // Left face -1,-1,-1, -1,-1,1, -1,1,-1, -1,1,1, // Bottom face -1,-1,-1, 1,-1,-1, -1,-1,1, 1,-1,1, // Top face -1,1,1, 1,1,1, -1,1,-1, 1,1,-1 }; private final float cubeTexCoordsStrip[] = { // Front face 0,0, 1,0, 0,1, 1,1, // Right face 0,0, 1,0, 0,1, 1,1, // Back face 0,0, 1,0, 0,1, 1,1, // Left face 0,0, 1,0, 0,1, 1,1, // Bottom face 0,0, 1,0, 0,1, 1,1, // Top face 0,0, 1,0, 0,1, 1,1 }; private FloatBuffer mTriangleVertices; private FloatBuffer mTriangleTexcoords; private final String mVertexShader = "uniform mat4 uMVPMatrix;\n" + "attribute vec4 aPosition;\n" + "attribute vec2 aTextureCoord;\n" + "varying vec2 vTextureCoord;\n" + "void main() {\n" + " gl_Position = uMVPMatrix * aPosition;\n" + " vTextureCoord = aTextureCoord;\n" + "}\n"; private final String mFragmentShader = "precision mediump float;\n" + "varying vec2 vTextureCoord;\n" + "uniform sampler2D sTexture;\n" + "void main() {\n" + " gl_FragColor = texture2D(sTexture, vTextureCoord);\n" + "}\n"; private float[] mMVPMatrix = new float[16]; private float[] mProjMatrix = new float[16]; private float[] mMMatrix = new float[16]; private float[] mVMatrix = new float[16]; private float[] mMMatrix2 = new float[16]; private int mProgram; private int mTextureID; private int muMVPMatrixHandle; private int maPositionHandle; private int maTextureHandle; private Context mContext; private static String TAG = "GLES20TriangleRenderer"; }

=>我设法在几个小时内实现了这个工作:)

==>因此,如果Android不是最好的平台,那么这似乎是一个非常好的和可行的平台,我开始在Android的设备上进行一些多媒体开发更多一点:)