应用投影和相机视口
在OpenGLES环境中,投影和相机视口使你绘制的对象以更接近物理对象的样子显示。这是通过对坐标精确的数学变换实现的。
-
投影-这种变换跟据所在
GLSurfaceView
的宽和高调整对象的坐标。如果没有此变换,对象会被不规则的视口扭曲。投射变换一般只需要在OpenGLview创建或发生变化时调用,代码写在renderer的onSurfaceChanged()
方法中。 -
相机视口-此变换基于一个虚拟相机的位置调整对象的坐标。注意OpenGLES并没有定义一个真的相机对象,而是提供了一些工具方法变换绘制对象的显示来模拟一个相机。一个相机视口的变换可能只在创建
GLSurfaceView
时调用,或跟据用户动作动态调用。
本文讲解了如何创建一个投影和一个相机视口然后应用到GLSurfaceView
的形状绘制过程。
定义一个投影
投影变换的数据是在GLSurfaceView.Renderer
类的 onSurfaceChanged()
方法中计算。下面的例子跟据GLSurfaceView
的宽和高,使用Matrix.frustumM()
方法计算出了一个投影变换Matrix
:
@Override publicvoid onSurfaceChanged(GL10 unused,int width,int height){ GLES20.glViewport(0,0, width, height); float ratio =(float) width / height; // 此投影矩阵在onDrawFrame()中将应用到对象的坐标 Matrix.frustumM(mProjMatrix,0,-ratio, ratio,-1,1,3,7); }
以下代码产生了一个投影矩阵mProjMatrix
,你可以把它在 onDrawFrame()
方法中与一个相机视口变换结合。
注: 只对你的对象应用一个投影变换一般会导制什么也看不到。通常,你必须也对其应用一个视口变换才能看到东西。
定义一个相机视口
再定义一个相机视口变换以使对绘制对象的变换处理变得完整。在下面的例子中,使用方法Matrix.setLookAtM()
计算相机视口变换,然后结合前面所计算的投影矩阵。结合后的变换矩阵之后传给要绘制的对象。
@Override publicvoid onDrawFrame(GL10 unused){ ... // 设置相机的位置(视口矩阵) 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); }
应用投影和相机视口变换
为了使用前面的合并后的投影和相机视口变换矩阵,修改你的图形对象的方法draw()
,接受结果矩阵并应用到你的形状上:
publicvoid draw(float[] mvpMatrix){// 传递计算出的变换矩阵 ... // 获得形状的变换矩阵的handle mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram,"uMVPMatrix"); // 应用投影和视口变换 GLES20.glUniformMatrix4fv(mMVPMatrixHandle,1,false, mvpMatrix,0); // 绘制三角形 GLES20.glDrawArrays(GLES20.GL_TRIANGLES,0, vertexCount); ... }
一旦你正确的计算和应用了投影和视口变换,你的图像将出现在正确的位置,看起来像下面这样:
图1.应用了投影和视口变换后绘制的三角形
现在你拥有了一个正确显示你的形状的应用了,是让你的图形动起来的时候了...嘿嘿...