您的位置:首页 > 移动开发 > Android开发

Android OpenGL ES 2.0 (二) 画立方体

2012-04-27 17:59 483 查看
画过三角形后,再来画立方体。

Activity还是和画三角形的一样,只是Renderer换了。

为加强立体感,加了旋转效果。

Test2Renderer.java

package com.android.jayce.test;

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.opengl.GLES20;
import android.opengl.Matrix;
import android.opengl.GLSurfaceView;
import android.os.SystemClock;

public class Test2Renderer implements GLSurfaceView.Renderer
{
private static final int BYTES_PER_FLOAT = 4;
private final FloatBuffer mCubePositions;
private final FloatBuffer mCubeColors;
private float[] mMVPMatrix = new float[16];
private float[] mViewMatrix = new float[16];
private float[] mModelMatrix = new float[16];
private float[] mProjectionMatrix = new float[16];
private int mMVPMatrixHandle;
private int mPositionHandle;
private int mColorHandle;
private int mProgramHandle;
private final int POSITION_DATA_SIZE = 3;
private final int COLOR_DATA_SIZE = 4;

public Test2Renderer()
{
final float cubePosition[] =
{
// Front face
-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,

// Right face
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,

// Back face
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,

// Left face
-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,

// Top face
-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,

// Bottom face
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,
};

final float[] cubeColor =
{
// Front face (red)
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,

// Right face (green)
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,

// Back face (blue)
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,

// Left face (yellow)
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f,

// Top face (cyan)
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,

// Bottom face (magenta)
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f
};

mCubePositions = ByteBuffer.allocateDirect(cubePosition.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mCubePositions.put(cubePosition).position(0);
mCubeColors = ByteBuffer.allocateDirect(cubeColor.length * BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
mCubeColors.put(cubeColor).position(0);
}

@Override
public void onDrawFrame(GL10 gl) {
// TODO Auto-generated method stub
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
long time = SystemClock.uptimeMillis() % 10000L;
float angleInDegrees = (360.0f / 10000.0f) * ((int) time);
GLES20.glUseProgram(mProgramHandle);
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix");
mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position");
mColorHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Color");

Matrix.setIdentityM(mModelMatrix, 0);
Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f);
Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 1.0f, 1.0f, 0.0f);
drawCube(mCubePositions, mCubeColors);
}

private void drawCube(final FloatBuffer cubePositionsBuffer, final FloatBuffer cubeColorsBuffer)
{
cubePositionsBuffer.position(0);
GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubePositionsBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);

cubeColorsBuffer.position(0);
GLES20.glVertexAttribPointer(mColorHandle, COLOR_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubeColorsBuffer);
GLES20.glEnableVertexAttribArray(mColorHandle);
Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);

GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 36);
}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// TODO Auto-generated method stub
GLES20.glViewport(0, 0, width, height);

final float ratio = (float) width / height;
final float left = -ratio;
final float right = ratio;
final float bottom = -1.0f;
final float top = 1.0f;
final float near = 1.0f;
final float far = 10.0f;

Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
// TODO Auto-generated method stub
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// Position the eye behind the origin.
final float eyeX = 0.0f;
final float eyeY = 0.0f;
final float eyeZ = -0.5f;

// We are looking toward the distance
final float lookX = 0.0f;
final float lookY = 0.0f;
final float lookZ = -5.0f;

// Set our up vector. This is where our head would be pointing were we holding the camera.
final float upX = 0.0f;
final float upY = 1.0f;
final float upZ = 0.0f;

// Set the view matrix. This matrix can be said to represent the camera position.
// NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
// view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);

final String vertexShader =
"uniform mat4 u_MVPMatrix;      \n"        // A constant representing the combined model/view/projection matrix.

+ "attribute vec4 a_Position;     \n"        // Per-vertex position information we will pass in.
+ "attribute vec4 a_Color;        \n"        // Per-vertex color information we will pass in.
+ "varying vec4 v_Color;          \n"        // This will be passed into the fragment shader.

+ "void main()                    \n"        // The entry point for our vertex shader.
+ "{                              \n"
+ "   v_Color = a_Color;          \n"        // Pass the color through to the fragment shader.
// It will be interpolated across the triangle.
+ "   gl_Position = u_MVPMatrix   \n"     // gl_Position is a special variable used to store the final position.
+ "               * a_Position;   \n"     // Multiply the vertex by the matrix to get the final point in
+ "}                              \n";    // normalized screen coordinates.

final String fragmentShader =
"precision mediump float;       \n"        // Set the default precision to medium. We don't need as high of a
// precision in the fragment shader.
+ "varying vec4 v_Color;          \n"        // This is the color from the vertex shader interpolated across the
// triangle per fragment.
+ "void main()                    \n"        // The entry point for our fragment shader.
+ "{                              \n"
+ "   gl_FragColor = v_Color;     \n"        // Pass the color directly through the pipeline.
+ "}                              \n";

int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER);
if(vertexShaderHandle != 0)
{
GLES20.glShaderSource(vertexShaderHandle, vertexShader);
GLES20.glCompileShader(vertexShaderHandle);

final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

if(compileStatus[0] == 0)
{
GLES20.glDeleteShader(vertexShaderHandle);
vertexShaderHandle = 0;
}
}

if(vertexShaderHandle == 0)
{
throw new RuntimeException("failed to creating vertex shader");
}

int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER);
if(fragmentShaderHandle != 0)
{
GLES20.glShaderSource(fragmentShaderHandle, fragmentShader);
GLES20.glCompileShader(fragmentShaderHandle);

final int[] compileStatus = new int[1];
GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0);

if(compileStatus[0] == 0)
{
GLES20.glDeleteShader(fragmentShaderHandle);
fragmentShaderHandle = 0;
}

}

if(fragmentShaderHandle == 0)
{
throw new RuntimeException("failed to create fragment shader");
}

mProgramHandle = GLES20.glCreateProgram();
if(mProgramHandle != 0)
{
GLES20.glAttachShader(mProgramHandle, vertexShaderHandle);
GLES20.glAttachShader(mProgramHandle, fragmentShaderHandle);

GLES20.glBindAttribLocation(mProgramHandle, 0, "a_Position");
GLES20.glBindAttribLocation(mProgramHandle, 1, "a_Color");

GLES20.glLinkProgram(mProgramHandle);

final int[] linkStatus = new int[1];
GLES20.glGetProgramiv(mProgramHandle, GLES20.GL_LINK_STATUS, linkStatus, 0);

if(linkStatus[0] == 0)
{
GLES20.glDeleteProgram(mProgramHandle);
mProgramHandle = 0;
}
}

if(mProgramHandle == 0)
{
throw new RuntimeException("failed to create program");
}

}

}


下面是效果图:





总结一下写此程序过程中犯的错误:

1,在构造方法里创建了mCubePositions和mCubeColors后忘了调mCubePositions.put(cubePosition).position(0)和mCubeColors.put(cubeColor).position(0)。

导致运行后是一片黑屏,什么都没画出来。这是个低级错误。以后不要再犯。

2,在onDrawFrame里glClear不小心把GL_DEPTH_BUFFER_BIT给删除了,然后出来的效果~~不是预想的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: