編輯:關於Android編程
上篇博客中我們提到了OpenGLES中繪制的兩種方法,頂點法和索引法。之前我們所使用的都是頂點法,這次繪制立方體使用索引法來繪制立方體。
上篇博客講到正方形的繪制,立方體是是由六個正方形組成,我們將這六個正方形繪制出來,立方體就繪制完畢了。既然選擇用索引法來繪制,立方體擁有八個頂點,我們先將這八個頂點列出來,放到一個數組中:
final float cubePositions[] = { -1.0f,1.0f,1.0f, //正面左上0 -1.0f,-1.0f,1.0f, //正面左下1 1.0f,-1.0f,1.0f, //正面右下2 1.0f,1.0f,1.0f, //正面右上3 -1.0f,1.0f,-1.0f, //反面左上4 -1.0f,-1.0f,-1.0f, //反面左下5 1.0f,-1.0f,-1.0f, //反面右下6 1.0f,1.0f,-1.0f, //反面右上7 };
正面由032和021兩個三角形組成,其他面諸如此類拆分,得到索引數組:
final short index[]={ 0,3,2,0,2,1, //正面 0,1,5,0,5,4, //左面 0,7,3,0,4,7, //上面 6,7,4,6,4,5, //後面 6,3,7,6,2,3, //右面 6,5,1,6,1,2 //下面 };
如果使用單一顏色,最後繪制出來的立方體不方便看效果,所以我們來繪制多種顏色的立方體出來。定義各個頂點的顏色:
//八個頂點的顏色,與頂點坐標一一對應 float color[] = { 0f,1f,0f,1f, 0f,1f,0f,1f, 0f,1f,0f,1f, 0f,1f,0f,1f, 1f,0f,0f,1f, 1f,0f,0f,1f, 1f,0f,0f,1f, 1f,0f,0f,1f, };
確定好立方體坐標和顏色後,我們需要創建頂點著色器和片元著色器,可使用與Android OpenGLES2.0(三)——等腰直角三角形和彩色的三角形中彩色三角形相同的頂點著色器和片元著色器。
接著其他的步驟與繪制三角形相同:
如果我們僅僅只做了以上事情,往往我們得不到一個正確的立方裡,反而會出現比較奇怪的立方體,比如這樣的:
這是因為我們沒有開啟深度測試GLES20.glEnable(GLES20.GL_DEPTH_TEST),並在繪制前清除深度緩存導致
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxibG9ja3F1b3RlPg0KCTxwPjxjb2RlPjxjb2RlPqOoMaOpyrLDtMrHye62yKO/PGJyIC8+DQoJye62yMbkyrW+zcrHuMPP88vYtePU2jNkysC959bQvuDA68njz/O7+rXEvuDA66Oou+bWxtf4seqjqaOsye62yLu6tObW0LTmtKLXxcO/uPbP88vYteOjqLvm1sbU2sbBxLvJz7XEo6m1xMnutsjWtaOhPGJyIC8+DQoJye62yNa1o6ha1rWjqdS9tPOjrNTywOvJ48/xu/rUvdS2oaM8YnIgLz4NCgnJ7rbI1rXKx7Tm1vzU2snutsi7urTmwO/D5rXEo6zO0sPH08PJ7rbIu7q05rXEzrvK/cC0uuLBv8nutsi7urTmtcS+q7bIoaPJ7rbIu7q05s67yv3Uvbjfo6zU8r6ryLe2yNS9uN+jrMS/x7C1xM/Uv6jSu7Djtry/ydans9YxNs67tcRaIEJ1ZmZlcqOs0rvQqbjfvLa1xM/Uv6jS0b6tv8nS1Nans9YzMs67tcRaIEJ1ZmZlcqOstavSu7Dj08MyNM67WiBCdWZmZXK+zdLRvq3X47m7wcuhozxiciAvPg0KCaOoMqOpzqrKssO00OjSqsnutsijvzxiciAvPg0KCdTasrvKudPDye62yLLiytS1xMqxuvKjrMjnufvO0sPHz8i75tbG0ru49r7gwOu9z738tcTO78zlo6zU2bvm1sa+4MDrvc/UtrXEzu/M5aOs1PK+4MDr1La1xM7vzOXS8s6quvO75tbGo6y74bDRvuDA6738tcTO78zluLK4x7X0o6zV4tH5tcTQp7n7sqKyu8rHztLDx8v5z6PN+7XEoaO2+NPQwcvJ7rbIu7qz5dLUuvOjrLvm1sbO78zltcTLs9Dyvs2yu8THw7TW2NKqwcujrLa8xNywtNXV1La9/KOoWta1o6nV/bOjz9TKvqOs1eK63LnYvPyhozxiciAvPg0KCcq1vMrJz6Os1rvSqrTm1NrJ7rbIu7qz5cf4o6zO3sLbyse38cb008PJ7rbIsuLK1KOsT3BlbkdM1NrP8cvYsbu75tbGyrG2vLvhs6LK1L2rye62yMr9vt3QtMjrtb27urPlx/jE2qOss/23x7X308PBy2dsRGVwdGhNYXNrKEdMX0ZBTFNFKcC0vfvWudC0yOuho9Xi0KnJ7rbIyv2+3bP9wcvTw9Pas6O55rXEsuLK1M3io6y7ub/J0tTT0NK70KnT0MiktcTTw82+o6yxyMjnu+bWxtL107C1yLXIoaM8YnIgLz4NCgmjqDOjqcb008PJ7rbIsuLK1DxiciAvPg0KCcq508MgZ2xFbmFibGUoR0xfREVQVEhfVEVTVCk7PGJyIC8+DQoJ1NrErMjPx+m/9srHvavQ6NKqu+bWxrXE0MLP8cvYtcR61rXT68nutsi7urPlx/jW0LbU06bOu9bDtcR61rW9+NDQsci9z6OsyOe5+7HIye62yLu6tObW0LXE1rXQoaOsxMfDtNPD0MLP8cvYtcTR1cmr1rW4/NDC1qG7urTm1tC21NOmz/HL2LXE0dXJq9a1oaM8YnIgLz4NCgm1q8rHv8nS1Mq508NnbERlcHRoRnVuYyhmdW5jKcC0ttTV4tbWxKzIz7LiytS3vcq9vfjQ0NDeuMShozxiciAvPg0KCcbk1tCyzsr9ZnVuY7XE1rW/ydLUzqpHTF9ORVZFUqOow7vT0LSmwO2jqaGiR0xfQUxXQVlTo6i0psDty/nT0KOpoaJHTF9MRVNTo6jQodPao6mhokdMX0xFUVVBTKOo0KHT2rXI09qjqaGiR0xfRVFVQUyjqLXI09qjqaGiR0xfR0VRVUFMo6i089PatcjT2qOpoaJHTF9HUkVBVEVSo6i089Pao6m78kdMX05PVEVRVUFMo6iyu7XI09qjqaOsxuTW0MSsyM/WtcrHR0xfTEVTU6GjPGJyIC8+DQoJ0ruw48C0vaujrMq508NnbERlcHRoRnVuYyhHTF9MRVFVQUwpO8C0se2079K7sOPO78zl1q685LXE1dq1srnYz7WhozxiciAvPg0KCaOoNKOpxvTTw8HLye62yLLiytSjrMTHw7TV4r7NsrvKytPD09rNrMqxu+bWxrK7zbjD987vzOWhozwvY29kZT48L2NvZGU+PC9wPg0KPC9ibG9ja3F1b3RlPg0KPGgxIGlkPQ=="具體實現">GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT)的。
加入後,我們即可得到正常的立方體:
openGL裡常出現深度測試,關於深度測試內容如下:具體實現
public class Cube extends Shape{
private FloatBuffer vertexBuffer,colorBuffer;
private ShortBuffer indexBuffer;
private final String vertexShaderCode =
"attribute vec4 vPosition;" +
"uniform mat4 vMatrix;"+
"varying vec4 vColor;"+
"attribute vec4 aColor;"+
"void main() {" +
" gl_Position = vMatrix*vPosition;" +
" vColor=aColor;"+
"}";
private final String fragmentShaderCode =
"precision mediump float;" +
"varying vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
private int mProgram;
final int COORDS_PER_VERTEX = 3;
final float cubePositions[] = {
-1.0f,1.0f,1.0f, //正面左上0
-1.0f,-1.0f,1.0f, //正面左下1
1.0f,-1.0f,1.0f, //正面右下2
1.0f,1.0f,1.0f, //正面右上3
-1.0f,1.0f,-1.0f, //反面左上4
-1.0f,-1.0f,-1.0f, //反面左下5
1.0f,-1.0f,-1.0f, //反面右下6
1.0f,1.0f,-1.0f, //反面右上7
};
final short index[]={
6,7,4,6,4,5, //後面
6,3,7,6,2,3, //右面
6,5,1,6,1,2, //下面
0,3,2,0,2,1, //正面
0,1,5,0,5,4, //左面
0,7,3,0,4,7, //上面
};
float color[] = {
0f,1f,0f,1f,
0f,1f,0f,1f,
0f,1f,0f,1f,
0f,1f,0f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f,
1f,0f,0f,1f,
};
private int mPositionHandle;
private int mColorHandle;
private float[] mViewMatrix=new float[16];
private float[] mProjectMatrix=new float[16];
private float[] mMVPMatrix=new float[16];
private int mMatrixHandler;
//頂點個數
private final int vertexCount = cubePositions.length / COORDS_PER_VERTEX;
//頂點之間的偏移量
private final int vertexStride = COORDS_PER_VERTEX * 4; // 每個頂點四個字節
public Cube(View mView) {
super(mView);
ByteBuffer bb = ByteBuffer.allocateDirect(
cubePositions.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(cubePositions);
vertexBuffer.position(0);
ByteBuffer dd = ByteBuffer.allocateDirect(
color.length * 4);
dd.order(ByteOrder.nativeOrder());
colorBuffer = dd.asFloatBuffer();
colorBuffer.put(color);
colorBuffer.position(0);
ByteBuffer cc= ByteBuffer.allocateDirect(index.length*2);
cc.order(ByteOrder.nativeOrder());
indexBuffer=cc.asShortBuffer();
indexBuffer.put(index);
indexBuffer.position(0);
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
//創建一個空的OpenGLES程序
mProgram = GLES20.glCreateProgram();
//將頂點著色器加入到程序
GLES20.glAttachShader(mProgram, vertexShader);
//將片元著色器加入到程序中
GLES20.glAttachShader(mProgram, fragmentShader);
//連接到著色器程序
GLES20.glLinkProgram(mProgram);
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
//開啟深度測試
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
//計算寬高比
float ratio=(float)width/height;
//設置透視投影
Matrix.frustumM(mProjectMatrix, 0, -ratio, ratio, -1, 1, 3, 20);
//設置相機位置
Matrix.setLookAtM(mViewMatrix, 0, 5.0f, 5.0f, 10.0f, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
//計算變換矩陣
Matrix.multiplyMM(mMVPMatrix,0,mProjectMatrix,0,mViewMatrix,0);
}
@Override
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT| GLES20.GL_DEPTH_BUFFER_BIT);
//將程序加入到OpenGLES2.0環境
GLES20.glUseProgram(mProgram);
//獲取變換矩陣vMatrix成員句柄
mMatrixHandler= GLES20.glGetUniformLocation(mProgram,"vMatrix");
//指定vMatrix的值
GLES20.glUniformMatrix4fv(mMatrixHandler,1,false,mMVPMatrix,0);
//獲取頂點著色器的vPosition成員句柄
mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
//啟用三角形頂點的句柄
GLES20.glEnableVertexAttribArray(mPositionHandle);
//准備三角形的坐標數據
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
//獲取片元著色器的vColor成員的句柄
mColorHandle = GLES20.glGetAttribLocation(mProgram, "aColor");
//設置繪制三角形的顏色
// GLES20.glUniform4fv(mColorHandle, 2, color, 0);
GLES20.glEnableVertexAttribArray(mColorHandle);
GLES20.glVertexAttribPointer(mColorHandle,4,
GLES20.GL_FLOAT,false,
0,colorBuffer);
//索引法繪制正方體
GLES20.glDrawElements(GLES20.GL_TRIANGLES,index.length, GLES20.GL_UNSIGNED_SHORT,indexBuffer);
//禁止頂點數組的句柄
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
}
源碼
所有的代碼全部在一個項目中,托管在Github上——Android OpenGLES 2.0系列博客的Demo
關於Android NDK開發的文章已經比較多了,我的博客中也分享了很多NDK開發相關經驗和技巧,今天簡單寫了一個 Android.mk 的示例模板,供初學者參考。本模板
本文實例講述了Android和JavaScript相互調用的方法。分享給大家供大家參考,具體如下:Html頁面和Java代碼結合的方式一般用在界面經常被更改 的情況下,可
安卓手機自誕生之日起無論多大運存,似乎清內存都是安卓用戶一個必不可少的動作,發展至今安卓系統版本幾經迭代、手機運存不斷飙升,軟硬件都有了翻天覆地的變化,那
Tab標簽頁是UI設計時經常使用的UI控件,可以實現多個分頁之間的快速切換,每個分頁可以顯示不同的內容。 TabHost相當於浏覽器中標簽頁分布的集合,而Tabspec