轉載請註明出處: http://blog.csdn.net/lb377463323/article/details/52136539
上篇文章中介紹瞭如何使用OpenGL ES2.0繪製三角形,本章將在上篇的基礎上進行講解,另附鏈接 OpenGL ES2.0入門之Android篇(一)——繪製三角形)
定義投影和相機視圖
- 在OpenGL ES環境中,投影和相機視圖讓繪製對象以更接近於人們肉眼所看到的實物對象的樣子顯示
- 投影: 前文講過,Android和OpenGL ES的座標系不一樣,如果沒有投影的話,繪製的圖像將會被拉伸變形,並且旋轉屏幕圖像顯示的比例也不一樣
- 相機視圖: 這種變換是基於一個虛擬相機的位置來調整繪製對象的座標
- 如果只定義了投影,通常會導致什麼也看不到,所以需要結合相機視圖才能看到屏幕上的繪圖
1. 在GLSurfaceView.Renderer類中定義一個投影
// mMVPMatrix是"Model View Projection Matrix"的縮寫
private final float[] mMVPMatrix = new float[16];
private final float[] mProjectionMatrix = new float[16];//定義投影矩陣變量
private final float[] mViewMatrix = new float[16];//定義相機視圖矩陣變量
@Override
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;//GLSurfaceView的寬高比
// 根據六個面定義投影矩陣 frustumM(float[] m, int offset, float left, float right, float bottom, float top, float near, float far)
Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
投影矩陣在onDrawFrame()方法中使用
Matrix.frustumM請參考Matrix源碼
2. 在onDrawFrame()方法中定義相機視圖
@Override
public void onDrawFrame(GL10 unused) {
...
// 設置相機的位置(視圖矩陣)
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// 將mProjectionMatrix和mViewMatrix矩陣相乘並賦給mMVPMatrix
Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
// 繪製形狀
mTriangle.draw(mMVPMatrix);
}
3. 修改三角形類中的draw()方法
一、修改vertexShaderCode爲
public class Triangle {
private final String vertexShaderCode =
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
" gl_Position = uMVPMatrix * vPosition;" +
"}";
private int mMVPMatrixHandle;
...
}
public void draw(float[] mvpMatrix) { // 傳遞計算出的變換矩陣
...
// 獲得形狀的變換矩陣的handle
mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// 把變換矩陣傳給着色器
GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
// 繪製三角形
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
// 禁用指向三角形的頂點數組
GLES20.glDisableVertexAttribArray(mPositionHandle);
}
此時運行應用程序,它能夠按照正確的比例繪製圖形,下一步就是添加動作
4. 旋轉圖形
在MyGlRenderer中添加旋轉矩陣代碼
private float[] mRotationMatrix = new float[16];
public void onDrawFrame(GL10 gl) {
float[] scratch = new float[16];
...
// 創建旋轉矩陣
long time = SystemClock.uptimeMillis() % 4000L;
float angle = 0.090f * ((int) time);
Matrix.setRotateM(mRotationMatrix, 0, angle, 0, 0, -1.0f);
// 將旋轉矩陣合併到投影和相機視圖變換矩陣中
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
// 繪製三角形
mTriangle.draw(scratch);
}
啓用持續渲染
public MyGLSurfaceView(Context context) {
...
// 將下面的代碼註釋掉
//setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
此時運行應用程序,可以觀察到圖形會一直旋轉,下面將展示如何監聽用戶的觸摸事件,讓用戶旋轉一個OpenGL ES對象
5. 在MyGLSurfaceView中設置觸摸監聽器
1.覆寫onTouchEvent()方法
private final float TOUCH_SCALE_FACTOR = 180.0f / 320;
private float mPreviousX;
private float mPreviousY;
@Override
public boolean onTouchEvent(MotionEvent e) {
// 這是Android中的基礎知識,這裏就不講解了
float x = e.getX();
float y = e.getY();
switch (e.getAction()) {
case MotionEvent.ACTION_MOVE:
float dx = x - mPreviousX;
float dy = y - mPreviousY;
// 反向旋轉至中線以上
if (y > getHeight() / 2) {
dx = dx * -1 ;
}
// 反向旋轉至中線左面
if (x < getWidth() / 2) {
dy = dy * -1 ;
}
mRenderer.setAngle(
mRenderer.getAngle() +
((dx + dy) * TOUCH_SCALE_FACTOR));
requestRender();//請求渲染
}
mPreviousX = x;
mPreviousY = y;
return true;
}
2.將setRenderMode的註釋去掉
public MyGLSurfaceView(Context context) {
...
// 只有在繪製數據改變時才繪製view
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
3.在MyGlRenderer中將旋轉角度暴露出去
public class MyGLRenderer implements GLSurfaceView.Renderer {
...
public volatile float mAngle;
public float getAngle() {
return mAngle;
}
public void setAngle(float angle) {
mAngle = angle;
}
}
4.在onDrawFrame()方法中調用旋轉角度
public void onDrawFrame(GL10 gl) {
...
float[] scratch = new float[16];
// 註釋掉生成旋轉角度的代碼
// long time = SystemClock.uptimeMillis() % 4000L;
// float angle = 0.090f * ((int) time);
// 添加mAngle
Matrix.setRotateM(mRotationMatrix, 0, mAngle, 0, 0, -1.0f);
// 合併旋轉矩陣到投影和相機視圖矩陣
Matrix.multiplyMM(scratch, 0, mMVPMatrix, 0, mRotationMatrix, 0);
// 繪製三角形
mTriangle.draw(scratch);
}
此時運行程序,在屏幕上划動旋轉三角形,顯示如下圖所示:
示例源碼:點擊下載源碼