画过三角形后,再来画立方体。
Activity还是和画三角形的一样,只是Renderer换了。
为加强立体感,加了旋转效果。
Test2Renderer.java
1 package com.android.jayce.test; 2 3 import java.nio.ByteBuffer; 4 import java.nio.ByteOrder; 5 import java.nio.FloatBuffer; 6 7 import javax.microedition.khronos.egl.EGLConfig; 8 import javax.microedition.khronos.opengles.GL10; 9 10 import android.opengl.GLES20; 11 import android.opengl.Matrix; 12 import android.opengl.GLSurfaceView; 13 import android.os.SystemClock; 14 15 public class Test2Renderer implements GLSurfaceView.Renderer 16 { 17 private static final int BYTES_PER_FLOAT = 4; 18 private final FloatBuffer mCubePositions; 19 private final FloatBuffer mCubeColors; 20 private float[] mMVPMatrix = new float[16]; 21 private float[] mViewMatrix = new float[16]; 22 private float[] mModelMatrix = new float[16]; 23 private float[] mProjectionMatrix = new float[16]; 24 private int mMVPMatrixHandle; 25 private int mPositionHandle; 26 private int mColorHandle; 27 private int mProgramHandle; 28 private final int POSITION_DATA_SIZE = 3; 29 private final int COLOR_DATA_SIZE = 4; 30 31 public Test2Renderer() 32 { 33 final float cubePosition[] = 34 { 35 // Front face 36 -1.0f, 1.0f, 1.0f, 37 -1.0f, -1.0f, 1.0f, 38 1.0f, 1.0f, 1.0f, 39 -1.0f, -1.0f, 1.0f, 40 1.0f, -1.0f, 1.0f, 41 1.0f, 1.0f, 1.0f, 42 43 // Right face 44 1.0f, 1.0f, 1.0f, 45 1.0f, -1.0f, 1.0f, 46 1.0f, 1.0f, -1.0f, 47 1.0f, -1.0f, 1.0f, 48 1.0f, -1.0f, -1.0f, 49 1.0f, 1.0f, -1.0f, 50 51 // Back face 52 1.0f, 1.0f, -1.0f, 53 1.0f, -1.0f, -1.0f, 54 -1.0f, 1.0f, -1.0f, 55 1.0f, -1.0f, -1.0f, 56 -1.0f, -1.0f, -1.0f, 57 -1.0f, 1.0f, -1.0f, 58 59 // Left face 60 -1.0f, 1.0f, -1.0f, 61 -1.0f, -1.0f, -1.0f, 62 -1.0f, 1.0f, 1.0f, 63 -1.0f, -1.0f, -1.0f, 64 -1.0f, -1.0f, 1.0f, 65 -1.0f, 1.0f, 1.0f, 66 67 // Top face 68 -1.0f, 1.0f, -1.0f, 69 -1.0f, 1.0f, 1.0f, 70 1.0f, 1.0f, -1.0f, 71 -1.0f, 1.0f, 1.0f, 72 1.0f, 1.0f, 1.0f, 73 1.0f, 1.0f, -1.0f, 74 75 // Bottom face 76 1.0f, -1.0f, -1.0f, 77 1.0f, -1.0f, 1.0f, 78 -1.0f, -1.0f, -1.0f, 79 1.0f, -1.0f, 1.0f, 80 -1.0f, -1.0f, 1.0f, 81 -1.0f, -1.0f, -1.0f, 82 }; 83 84 final float[] cubeColor = 85 { 86 // Front face (red) 87 1.0f, 0.0f, 0.0f, 1.0f, 88 1.0f, 0.0f, 0.0f, 1.0f, 89 1.0f, 0.0f, 0.0f, 1.0f, 90 1.0f, 0.0f, 0.0f, 1.0f, 91 1.0f, 0.0f, 0.0f, 1.0f, 92 1.0f, 0.0f, 0.0f, 1.0f, 93 94 // Right face (green) 95 0.0f, 1.0f, 0.0f, 1.0f, 96 0.0f, 1.0f, 0.0f, 1.0f, 97 0.0f, 1.0f, 0.0f, 1.0f, 98 0.0f, 1.0f, 0.0f, 1.0f, 99 0.0f, 1.0f, 0.0f, 1.0f, 100 0.0f, 1.0f, 0.0f, 1.0f, 101 102 // Back face (blue) 103 0.0f, 0.0f, 1.0f, 1.0f, 104 0.0f, 0.0f, 1.0f, 1.0f, 105 0.0f, 0.0f, 1.0f, 1.0f, 106 0.0f, 0.0f, 1.0f, 1.0f, 107 0.0f, 0.0f, 1.0f, 1.0f, 108 0.0f, 0.0f, 1.0f, 1.0f, 109 110 // Left face (yellow) 111 1.0f, 1.0f, 0.0f, 1.0f, 112 1.0f, 1.0f, 0.0f, 1.0f, 113 1.0f, 1.0f, 0.0f, 1.0f, 114 1.0f, 1.0f, 0.0f, 1.0f, 115 1.0f, 1.0f, 0.0f, 1.0f, 116 1.0f, 1.0f, 0.0f, 1.0f, 117 118 // Top face (cyan) 119 0.0f, 1.0f, 1.0f, 1.0f, 120 0.0f, 1.0f, 1.0f, 1.0f, 121 0.0f, 1.0f, 1.0f, 1.0f, 122 0.0f, 1.0f, 1.0f, 1.0f, 123 0.0f, 1.0f, 1.0f, 1.0f, 124 0.0f, 1.0f, 1.0f, 1.0f, 125 126 // Bottom face (magenta) 127 1.0f, 0.0f, 1.0f, 1.0f, 128 1.0f, 0.0f, 1.0f, 1.0f, 129 1.0f, 0.0f, 1.0f, 1.0f, 130 1.0f, 0.0f, 1.0f, 1.0f, 131 1.0f, 0.0f, 1.0f, 1.0f, 132 1.0f, 0.0f, 1.0f, 1.0f 133 }; 134 135 mCubePositions = ByteBuffer.allocateDirect(cubePosition.length * BYTES_PER_FLOAT) 136 .order(ByteOrder.nativeOrder()).asFloatBuffer(); 137 mCubePositions.put(cubePosition).position(0); 138 mCubeColors = ByteBuffer.allocateDirect(cubeColor.length * BYTES_PER_FLOAT) 139 .order(ByteOrder.nativeOrder()).asFloatBuffer(); 140 mCubeColors.put(cubeColor).position(0); 141 } 142 143 @Override 144 public void onDrawFrame(GL10 gl) { 145 // TODO Auto-generated method stub 146 GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); 147 long time = SystemClock.uptimeMillis() % 10000L; 148 float angleInDegrees = (360.0f / 10000.0f) * ((int) time); 149 GLES20.glUseProgram(mProgramHandle); 150 mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgramHandle, "u_MVPMatrix"); 151 mPositionHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Position"); 152 mColorHandle = GLES20.glGetAttribLocation(mProgramHandle, "a_Color"); 153 154 Matrix.setIdentityM(mModelMatrix, 0); 155 Matrix.translateM(mModelMatrix, 0, 0.0f, 0.0f, -5.0f); 156 Matrix.rotateM(mModelMatrix, 0, angleInDegrees, 1.0f, 1.0f, 0.0f); 157 drawCube(mCubePositions, mCubeColors); 158 } 159 160 private void drawCube(final FloatBuffer cubePositionsBuffer, final FloatBuffer cubeColorsBuffer) 161 { 162 cubePositionsBuffer.position(0); 163 GLES20.glVertexAttribPointer(mPositionHandle, POSITION_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubePositionsBuffer); 164 GLES20.glEnableVertexAttribArray(mPositionHandle); 165 166 cubeColorsBuffer.position(0); 167 GLES20.glVertexAttribPointer(mColorHandle, COLOR_DATA_SIZE, GLES20.GL_FLOAT, false, 0, cubeColorsBuffer); 168 GLES20.glEnableVertexAttribArray(mColorHandle); 169 Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0); 170 Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0); 171 172 GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mMVPMatrix, 0); 173 GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 36); 174 } 175 176 @Override 177 public void onSurfaceChanged(GL10 gl, int width, int height) { 178 // TODO Auto-generated method stub 179 GLES20.glViewport(0, 0, width, height); 180 181 final float ratio = (float) width / height; 182 final float left = -ratio; 183 final float right = ratio; 184 final float bottom = -1.0f; 185 final float top = 1.0f; 186 final float near = 1.0f; 187 final float far = 10.0f; 188 189 Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far); 190 } 191 192 @Override 193 public void onSurfaceCreated(GL10 gl, EGLConfig config) { 194 // TODO Auto-generated method stub 195 GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 196 GLES20.glEnable(GLES20.GL_CULL_FACE); 197 GLES20.glEnable(GLES20.GL_DEPTH_TEST); 198 // Position the eye behind the origin. 199 final float eyeX = 0.0f; 200 final float eyeY = 0.0f; 201 final float eyeZ = -0.5f; 202 203 // We are looking toward the distance 204 final float lookX = 0.0f; 205 final float lookY = 0.0f; 206 final float lookZ = -5.0f; 207 208 // Set our up vector. This is where our head would be pointing were we holding the camera. 209 final float upX = 0.0f; 210 final float upY = 1.0f; 211 final float upZ = 0.0f; 212 213 // Set the view matrix. This matrix can be said to represent the camera position. 214 // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and 215 // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose. 216 Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ); 217 218 final String vertexShader = 219 "uniform mat4 u_MVPMatrix; \n" // A constant representing the combined model/view/projection matrix. 220 221 + "attribute vec4 a_Position; \n" // Per-vertex position information we will pass in. 222 + "attribute vec4 a_Color; \n" // Per-vertex color information we will pass in. 223 + "varying vec4 v_Color; \n" // This will be passed into the fragment shader. 224 225 + "void main() \n" // The entry point for our vertex shader. 226 + "{ \n" 227 + " v_Color = a_Color; \n" // Pass the color through to the fragment shader. 228 // It will be interpolated across the triangle. 229 + " gl_Position = u_MVPMatrix \n" // gl_Position is a special variable used to store the final position. 230 + " * a_Position; \n" // Multiply the vertex by the matrix to get the final point in 231 + "} \n"; // normalized screen coordinates. 232 233 final String fragmentShader = 234 "precision mediump float; \n" // Set the default precision to medium. We don't need as high of a 235 // precision in the fragment shader. 236 + "varying vec4 v_Color; \n" // This is the color from the vertex shader interpolated across the 237 // triangle per fragment. 238 + "void main() \n" // The entry point for our fragment shader. 239 + "{ \n" 240 + " gl_FragColor = v_Color; \n" // Pass the color directly through the pipeline. 241 + "} \n"; 242 243 int vertexShaderHandle = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); 244 if(vertexShaderHandle != 0) 245 { 246 GLES20.glShaderSource(vertexShaderHandle, vertexShader); 247 GLES20.glCompileShader(vertexShaderHandle); 248 249 final int[] compileStatus = new int[1]; 250 GLES20.glGetShaderiv(vertexShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0); 251 252 if(compileStatus[0] == 0) 253 { 254 GLES20.glDeleteShader(vertexShaderHandle); 255 vertexShaderHandle = 0; 256 } 257 } 258 259 if(vertexShaderHandle == 0) 260 { 261 throw new RuntimeException("failed to creating vertex shader"); 262 } 263 264 int fragmentShaderHandle = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); 265 if(fragmentShaderHandle != 0) 266 { 267 GLES20.glShaderSource(fragmentShaderHandle, fragmentShader); 268 GLES20.glCompileShader(fragmentShaderHandle); 269 270 final int[] compileStatus = new int[1]; 271 GLES20.glGetShaderiv(fragmentShaderHandle, GLES20.GL_COMPILE_STATUS, compileStatus, 0); 272 273 if(compileStatus[0] == 0) 274 { 275 GLES20.glDeleteShader(fragmentShaderHandle); 276 fragmentShaderHandle = 0; 277 } 278 279 } 280 281 if(fragmentShaderHandle == 0) 282 { 283 throw new RuntimeException("failed to create fragment shader"); 284 } 285 286 mProgramHandle = GLES20.glCreateProgram(); 287 if(mProgramHandle != 0) 288 { 289 GLES20.glAttachShader(mProgramHandle, vertexShaderHandle); 290 GLES20.glAttachShader(mProgramHandle, fragmentShaderHandle); 291 292 GLES20.glBindAttribLocation(mProgramHandle, 0, "a_Position"); 293 GLES20.glBindAttribLocation(mProgramHandle, 1, "a_Color"); 294 295 GLES20.glLinkProgram(mProgramHandle); 296 297 final int[] linkStatus = new int[1]; 298 GLES20.glGetProgramiv(mProgramHandle, GLES20.GL_LINK_STATUS, linkStatus, 0); 299 300 if(linkStatus[0] == 0) 301 { 302 GLES20.glDeleteProgram(mProgramHandle); 303 mProgramHandle = 0; 304 } 305 } 306 307 if(mProgramHandle == 0) 308 { 309 throw new RuntimeException("failed to create program"); 310 } 311 312 } 313 314 }
下面是效果图:
总结一下写此程序过程中犯的错误:
1,在构造方法里创建了mCubePositions和mCubeColors后忘了调mCubePositions.put(cubePosition).position(0)和mCubeColors.put(cubeColor).position(0)。
导致运行后是一片黑屏,什么都没画出来。这是个低级错误。以后不要再犯。
2,在onDrawFrame里glClear不小心把GL_DEPTH_BUFFER_BIT给删除了,然后出来的效果~~不是预想的。