立方體實現的代碼 import android.opengl.GLSurfaceView; import android.opengl.GLU; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class OpenGLRender implements GLSurfaceView.Renderer { private float[] vertices = { -1.0f, 1.0f, 1f, //top left -1.0f, -1.0f, 1f, // bottom left 1.0f, -1.0f, 1f, //top right -1.0f, 1.0f, 1f, //bottom left 1.0f, -1.0f, 1f, //bottom right 1.0f, 1.0f, 1f, //top right //前面 1.0f, 1.0f, 1f, //top lest 1.0f, -1.0f, 1f, // bottom left 1.0f, -1.0f, -1f, //top right 1.0f, 1.0f, 1f, //bottom left 1.0f, -1.0f, -1.0f, //bottom right 1.0f, 1.0f, -1f, //top right //右面 -1.0f, 1.0f, -1.0f, //top lest -1.0f, -1.0f, -1.0f, // bottom left -1.0f, 1.0f, 1.0f, //top right -1.0f, -1.0f, -1.0f, //bottom left -1.0f, -1.0f, 1.0f, //bottom right -1.0f, 1.0f, 1.0f, //top right //左面 1.0f, 1.0f, -1.0f, //top lest 1.0f, -1.0f, -1.0f, // bottom left -1.0f, -1.0f, -1.0f, //top right 1.0f, 1.0f, -1.0f, //bottom left -1.0f, -1.0f, -1.0f, //bottom right -1.0f, 1.0f, -1.0f, //top right //後面 -1.0f, 1.0f, -1.0f, //top lest -1.0f, 1.0f, 1.0f, // bottom left 1.0f, 1.0f, -1.0f, //top right -1.0f, 1.0f, 1.0f, //bottom left 1.0f, 1.0f, 1.0f, //bottom right 1.0f, 1.0f, -1.0f, //-top right //上面 -1.0f, -1.0f, 1.0f, //top lest -1.0f, -1.0f, -1.0f, // bottom left 1.0f, -1.0f, -1.0f, //top right -1.0f, -1.0f, 1.0f, //bottom left 1.0f, -1.0f, -1.0f, //bottom right 1.0f, -1.0f, 1.0f, //top right //下面 }; //立方體的顏色 private float[] colors = { 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0f, 1f, 1f, 1f, 0f, 1f, 1f, 1f, 0f, 1f, 1f, 1f, 0f, 1f, 1f, 1f, 0f, 1f, 1f, 1f, 0f, 1f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0f, 0f, 1f, 1f, 0.5f,0f,1f,1f, 0.5f,0f,1f,1f, 0.5f,0f,1f,1f, 0.5f,0f,1f,1f, 0.5f,0f,1f,1f, 0.5f,0f,1f,1f, 1f,0f,0.5f,1f, 1f,0f,0.5f,1f, 1f,0f,0.5f,1f, 1f,0f,0.5f,1f, 1f,0f,0.5f,1f, 1f,0f,0.5f,1f, }; FloatBuffer verBuffer;//頂點緩衝 FloatBuffer colorBuffer;//顏色緩衝 float rx = -70f; public OpenGLRender(){ ByteBuffer vbb =ByteBuffer.allocateDirect(vertices.length*4); vbb.order(ByteOrder.nativeOrder()); verBuffer =vbb.asFloatBuffer(); verBuffer.put(vertices); verBuffer.position(0); ByteBuffer cbb =ByteBuffer.allocateDirect(colors.length*4); cbb.order(ByteOrder.nativeOrder()); colorBuffer =cbb.asFloatBuffer(); colorBuffer.put(colors); colorBuffer.position(0); } @Override public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) { //啓用深度測試 gl10.glEnable(GL10.GL_DEPTH_TEST); //所做深度測試的類型 gl10.glDepthFunc(GL10.GL_DITHER); //透明背景 gl10.glClearColor(1.0f,1.0f,1.0f,0.0f); //啓用陰影平滑 gl10.glShadeModel(GL10.GL_SMOOTH); //清除深度緩存 gl10.glClearDepthf(1.0f); gl10.glEnable(GL10.GL_TEXTURE_2D); //告訴系統對透視進行修正 gl10.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT,GL10.GL_FASTEST); } @Override public void onSurfaceChanged(GL10 gl10, int width, int height) { gl10.glViewport(0,0,width,height); gl10.glMatrixMode(GL10.GL_PROJECTION); gl10.glLoadIdentity(); GLU.gluPerspective(gl10,45.0f,(float)width/(float)height,0.1f,100.f); gl10.glMatrixMode(GL10.GL_MODELVIEW); gl10.glLoadIdentity(); } @Override public void onDrawFrame(GL10 gl10) { //清除深度和顏色緩存 gl10.glClearColor(1.0f,1.0f,1.0f,0.0f); gl10.glClear(GL10.GL_COLOR_BUFFER_BIT|GL10.GL_DEPTH_BUFFER_BIT); gl10.glMatrixMode(GL10.GL_MODELVIEW);//設置矩陣模式 draw(gl10); } public void draw(GL10 gl){ gl.glFrontFace(GL10.GL_CCW); gl.glEnable(GL10.GL_CULL_FACE); gl.glCullFace(GL10.GL_BACK); //開啓頂點和紋理緩衝 gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glVertexPointer(3,GL10.GL_FLOAT,0,verBuffer); gl.glColorPointer(4,GL10.GL_FLOAT,0,colorBuffer); gl.glLoadIdentity(); gl.glTranslatef(0,0,-5); gl.glRotatef(45f,0f,1f,0f);//往右邊(Y軸)傾斜45度 gl.glRotatef(rx,1f,0f,0f);//根據每次得到的角度往上面傾斜(x軸) gl.glDrawArrays(GL10.GL_TRIANGLES,0,vertices.length); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_COLOR_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glDisable(GL10.GL_CULL_FACE); rx--;//旋轉角度減1 } }
球體實現的代碼
import android.opengl.GLSurfaceView; import android.opengl.GLU; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; public class OpenGLRender2 implements GLSurfaceView.Renderer { // 環境光 private final float[] mat_ambient = { 0.2f, 0.3f, 0.4f, 1.0f }; private FloatBuffer mat_ambient_buf; // 平行入射光 private final float[] mat_diffuse = { 0.4f, 0.6f, 0.8f, 1.0f }; private FloatBuffer mat_diffuse_buf; // 高亮區域 private final float[] mat_specular = { 0.2f * 0.4f, 0.2f * 0.6f, 0.2f * 0.8f, 1.0f }; private FloatBuffer mat_specular_buf; private Sphere mSphere = new Sphere(); public volatile float mLightX = 10f; public volatile float mLightY = 10f; public volatile float mLightZ = 10f; @Override public void onDrawFrame(GL10 gl) { // 清晰屏幕和深度緩存 gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // 重置當前的模型觀察矩陣 gl.glLoadIdentity(); gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); // 材質 gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, mat_ambient_buf); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, mat_diffuse_buf); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, mat_specular_buf); // 鏡面指數 0~128 越小越粗糙 gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 96.0f); //光源位置 float[] light_position = {mLightX, mLightY, mLightZ, 0.0f}; ByteBuffer mpbb = ByteBuffer.allocateDirect(light_position.length*4); mpbb.order(ByteOrder.nativeOrder()); FloatBuffer mat_posiBuf = mpbb.asFloatBuffer(); mat_posiBuf.put(light_position); mat_posiBuf.position(0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, mat_posiBuf); gl.glTranslatef(0.0f, 0.0f, -3.0f); mSphere.draw(gl); } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // 設置輸出屏幕大小 gl.glViewport(0, 0, width, height); // 設置投影矩陣 gl.glMatrixMode(GL10.GL_PROJECTION); // 重置投影矩陣 gl.glLoadIdentity(); // 設置視口大小 // gl.glFrustumf(0, width, 0, height, 0.1f, 100.0f); GLU.gluPerspective(gl, 90.0f, (float) width / height, 0.1f, 50.0f); // 選擇模型觀察矩陣 gl.glMatrixMode(GL10.GL_MODELVIEW); // 重置模型觀察矩陣 gl.glLoadIdentity(); } @Override public void onSurfaceCreated(GL10 gl, EGLConfig arg1) { // 對透視進行修正 gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); // 背景:黑色 gl.glClearColor(0, 0.0f, 0.0f, 0.0f); // 啓動陰影平滑 gl.glShadeModel(GL10.GL_SMOOTH); // 復位深度緩存 gl.glClearDepthf(1.0f); // 啓動深度測試 gl.glEnable(GL10.GL_DEPTH_TEST); // 所做深度測試的類型 gl.glDepthFunc(GL10.GL_LEQUAL); initBuffers(); } private void initBuffers() { ByteBuffer bufTemp = ByteBuffer.allocateDirect(mat_ambient.length * 4); bufTemp.order(ByteOrder.nativeOrder()); mat_ambient_buf = bufTemp.asFloatBuffer(); mat_ambient_buf.put(mat_ambient); mat_ambient_buf.position(0); bufTemp = ByteBuffer.allocateDirect(mat_diffuse.length * 4); bufTemp.order(ByteOrder.nativeOrder()); mat_diffuse_buf = bufTemp.asFloatBuffer(); mat_diffuse_buf.put(mat_diffuse); mat_diffuse_buf.position(0); bufTemp = ByteBuffer.allocateDirect(mat_specular.length * 4); bufTemp.order(ByteOrder.nativeOrder()); mat_specular_buf = bufTemp.asFloatBuffer(); mat_specular_buf.put(mat_specular); mat_specular_buf.position(0); } }
import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; // 計算球面頂點 public class Sphere { public void draw(GL10 gl) { float angleA, angleB; float cos, sin; float r1, r2; float h1, h2; float step = 2.0f; float[][] v = new float[32][3]; ByteBuffer vbb; FloatBuffer vBuf; vbb = ByteBuffer.allocateDirect(v.length * v[0].length * 4); vbb.order(ByteOrder.nativeOrder()); vBuf = vbb.asFloatBuffer(); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); for (angleA = -90.0f; angleA < 90.0f; angleA += step) { int n = 0; r1 = (float)Math.cos(angleA * Math.PI / 180.0); r2 = (float)Math.cos((angleA + step) * Math.PI / 180.0); h1 = (float)Math.sin(angleA * Math.PI / 180.0); h2 = (float)Math.sin((angleA + step) * Math.PI / 180.0); // 固定緯度, 360 度旋轉遍歷一條緯線 for (angleB = 0.0f; angleB <= 360.0f; angleB += step) { cos = (float)Math.cos(angleB * Math.PI / 180.0); sin = -(float)Math.sin(angleB * Math.PI / 180.0); v[n][0] = (r2 * cos); v[n][1] = (h2); v[n][2] = (r2 * sin); v[n + 1][0] = (r1 * cos); v[n + 1][1] = (h1); v[n + 1][2] = (r1 * sin); vBuf.put(v[n]); vBuf.put(v[n + 1]); n += 2; if(n>31){ vBuf.position(0); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuf); gl.glNormalPointer(GL10.GL_FLOAT, 0, vBuf); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, n); n = 0; angleB -= step; } } vBuf.position(0); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuf); gl.glNormalPointer(GL10.GL_FLOAT, 0, vBuf); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, n); } gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); } }
頁面顯示
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); GLSurfaceView glSurfaceView = (GLSurfaceView)findViewById(R.id.glsurfaceview); glSurfaceView.setRenderer(new OpenGLRender()); mRenderer = new OpenGLRender2(); GLSurfaceView glsurfaceview2 = (GLSurfaceView)findViewById(R.id.glsurfaceview2); glsurfaceview2.setRenderer(mRenderer); glsurfaceview2.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { int action = event.getActionMasked(); switch (action) { case MotionEvent.ACTION_DOWN: mDownX = event.getX(); mDownY = event.getY(); return true; case MotionEvent.ACTION_UP: return true; case MotionEvent.ACTION_MOVE: float mX = event.getX(); float mY = event.getY(); mRenderer.mLightX += (mX - mDownX) / 10; mRenderer.mLightY -= (mY - mDownY) / 10; mDownX = mX; mDownY = mY; return true; default: return false; } } }); }
頁面佈局xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" tools:context=".MainActivity"> <android.opengl.GLSurfaceView android:id="@+id/glsurfaceview" android:layout_width="100px" android:layout_height="100px" android:layout_centerInParent="true"/> <android.opengl.GLSurfaceView android:id="@+id/glsurfaceview2" android:layout_width="500px" android:layout_height="200px" android:layout_marginTop="20px" android:layout_below="@+id/glsurfaceview" android:layout_centerInParent="true"/> </RelativeLayout>