Android OpenGL ES 2.0繪圖:應(yīng)用投影和相機視圖
在OpenGL ES環(huán)境中,投影和相機視圖讓繪制對象以更接近于人們?nèi)庋鬯吹降膶嵨飳ο蟮臉幼语@示。這項仿真技術(shù)是通過對繪制對象的坐標(biāo)進行精確的數(shù)學(xué)變換而實現(xiàn)的。
投影:這種變換是根據(jù)所在GLSurfaceView的寬和高調(diào)整繪制對象的坐標(biāo)。
如果沒有此變換,對象會被不規(guī)則比例的視圖所扭曲變形。
通常一個投影變換只有當(dāng)創(chuàng)建OpenGLView或你的renderer類的 onSurfaceChange()方法發(fā)生變化時才被計算,更多關(guān)于OpenGL ES預(yù)測和坐標(biāo)映射的信息,請參閱代碼Mapping Coordinates for Drawn Objects。
相機視圖:這種變換是基于一個虛擬相機的位置來調(diào)整繪制對象的坐標(biāo)。需要主要的 是,OpenGL ES并沒有定義一個真實的相機對象,而是提供了一些工具方法變換繪制對象的顯示來模擬一個相機。一個相機視圖變換可能在創(chuàng)建GLSurfaceView時 被計算一次,或根據(jù)用戶行為或應(yīng)用程序功能動態(tài)地改變。
這一節(jié)將描述如何創(chuàng)建一個投影和一個相機視圖,并將它們應(yīng)用于你的GLSurfaceView的形狀繪制過程中。
一、定義一個投影
一個投影變換的數(shù)據(jù)是在GLSurfaceView.Renderer類的 onSurfaceChanged()方法中計算得到的。下面的示例代碼演示了根據(jù)傳入GLSurfaceView的寬和高計算比例,并使用Matrix 類frustumM()方法來填充一個投影變換:
- [java] view plaincopyprint?
- @Override
- public void onSurfaceChanged(GL10 unused, int width, int height) {
- GLES20.glViewport(0, 0, width, height);
- float ratio = (float) width / height;
- // 在onDrawFrame()方法中,將投影矩陣應(yīng)用到對象的坐標(biāo)
- Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
- }
這段代碼填充了一個投影矩陣:mProjMatrix,可以把它與一個相機視圖變換在onDrawFrame()方法中結(jié)合起來使用。
注:如果只是一個投影變換應(yīng)用到你的繪制對象中,通常會導(dǎo)致什么也看不到。一般來說,你必須再申請一個相機視圖變換才能看到屏幕上的東東。
二、定義一個相機視圖
添加一個相機視圖變換讓你的繪制對象的變換流程變得更加完整。在下面的示例代碼中,使用Matrix.setLookAtM()方法來計算相機視圖變換,然后結(jié)合前面所計算的投影矩陣。將合并后的變換矩陣傳遞給繪制的形狀。
- [java] view plaincopyprint?
- @Override
- public void onDrawFrame(GL10 unused) {
- ...
- // 設(shè)置相機的位置(視圖矩陣)
- Matrix.setLookAtM(mVMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
- // 計算投影和視圖變換
- Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
- // 繪制形狀
- mTriangle.draw(mMVPMatrix);
- }
三、應(yīng)用投影和相機視圖變換
為了使用合并后的投影和相機視圖變換矩陣,需要修改你的圖形對象的draw()方法,接收聯(lián)合變換矩陣并應(yīng)用到你的形狀上:
- [java] view plaincopyprint?
- public void draw(float[] mvpMatrix) { // 傳遞計算出的變換矩陣
- ...
- // 獲得形狀的變換矩陣的handle
- mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
- // 應(yīng)用投影和視圖變換
- GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0);
- // 繪制三角形
- GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount);
- ...
- }