使用Android OpenGL ES 2.0绘图之四:应用投影和相机视口
传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229
在OpenGL ES环境中,投影和相机视图让绘制对象以更接近于人们肉眼所看到的实物对象的样子显示。这项仿真技术是通过对绘制对象的坐标进行精确的数学变换而实现的。
投影:这种变换是根据所在GLSurfaceView的宽和高调整绘制对象的坐标。如果没有此变换,对象会被不规则比例的视图所扭曲变形。通常一个投影变换只有当创建OpenGLView或你的renderer类的onSurfaceChange()方法发生变化时才被计算,更多关于OpenGL ES预测和坐标映射的信息,请参阅代码Mapping Coordinates for Drawn Objects。
相机视图:这种变换是基于一个虚拟相机的位置来调整绘制对象的坐标。需要主要的是,OpenGL ES并没有定义一个真实的相机对象,而是提供了一些工具方法变换绘制对象的显示来模拟一个相机。一个相机视图变换可能在创建GLSurfaceView时被计算一次,或根据用户行为或应用程序功能动态地改变。
这一节将描述如何创建一个投影和一个相机视口,并将它们应用于你的GLSurfaceView的形状绘制过程中。
1定义一个投影
一个投影变换的数据是在GLSurfaceView.Renderer类的onSurfaceChanged()方法中计算得到的。下面的示例代码演示了根据传入GLSurfaceView的宽和高计算比例,并使用Matrix类frustumM()方法来填充一个投影变换:@Override public void 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()方法中结合起来使用。
注:如果只是一个投影变换应用到你的绘制对象中,通常会导致什么也看不到。一般来说,你必须再申请一个相机视图变换才能看到屏幕上的东东。
2定义一个相机视口
添加一个相机视口变换让你的绘制对象的变换流程变得更加完整。在下面的示例代码中,使用Matrix.setLookAtM()方法来计算相机视口变换,然后结合前面所计算的投影矩阵。将合并后的变换矩阵传递给绘制的形状。@Override public void 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); }
3应用投影和相机视口变换
为了使用合并后的投影和相机视口变换矩阵,需要修改你的图形对象的draw()方法,接收联合变换矩阵并应用到你的形状上: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); ... }
一旦你已经正确地计算和应用了投影和相机视口变换,你的图形对象将按照正确的比例进行绘制,看起来应该像下面这样:
看看现在你的这个应用程序,它能够按照正确的比例绘制图形,是时候让你的图形动起来了。