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