Android官方开发文档Training系列课程中文版:OpenGL绘图之应用投影与相机视图
2016-05-24 10:04
651 查看
原文地址:http://android.xsoftlab.net/training/graphics/opengl/projection.html##transform
在OpenGL ES环境中,投影相机View可以将所绘制的图形模拟成现实中所看到的物理性状。这种物理模拟是通过改变对象的数字坐标实现的:
投影 - 这基于GLSurfaceView的高宽的坐标转换而实现。如果不采用这种计算,所绘制的对象就会由于窗口的不平等比例所曲解。投影转换只有在OpenGL视图的比例被确定或渲染器的onSurfaceChanged()方法发生改变后才会被计算。有关更多OpenGL的坐标映射关系,请参见Mapping Coordinates for Drawn Objects。
相机视图 - 这基于虚拟相机的位置转变而实现。要着重注意OpenGL并没有定义真实的相机对象,而是提供了一种通过转换图形对象来模拟相机的方法。一个相机视图转换只有在GLSurfaceView被确定的时候才会开始计算,或者基于用户的行为或者应用的功能而动态的发生改变。
这节课描述了如何创建一个投影相机视图,并将其应用到图形的绘制中。
这些代码会填充投影矩阵:mProjectionMatrix,它可以被用来与相机视图转换整合。
Note: 仅仅将投影转换应用到要绘制的物体上,一般来说是没什么意义的。通常情况下,还必须将相机视图转换也一并应用。这样才能使物体呈现在屏幕上。
接下来,修改绘制物体对象的draw()方法,以便可以接收整合后的矩阵,然后将其应用到图形中:
如果有正确的计算结果以及正确的使用了整合后的矩阵,那么图形会以正确的比例被绘制出来,最后看起来的效果应该是这样子的:
现在程序就可以正常显示比例正常的图形了,是时候为图形添加动作了。
在OpenGL ES环境中,投影相机View可以将所绘制的图形模拟成现实中所看到的物理性状。这种物理模拟是通过改变对象的数字坐标实现的:
投影 - 这基于GLSurfaceView的高宽的坐标转换而实现。如果不采用这种计算,所绘制的对象就会由于窗口的不平等比例所曲解。投影转换只有在OpenGL视图的比例被确定或渲染器的onSurfaceChanged()方法发生改变后才会被计算。有关更多OpenGL的坐标映射关系,请参见Mapping Coordinates for Drawn Objects。
相机视图 - 这基于虚拟相机的位置转变而实现。要着重注意OpenGL并没有定义真实的相机对象,而是提供了一种通过转换图形对象来模拟相机的方法。一个相机视图转换只有在GLSurfaceView被确定的时候才会开始计算,或者基于用户的行为或者应用的功能而动态的发生改变。
这节课描述了如何创建一个投影相机视图,并将其应用到图形的绘制中。
定义投影
投影转换的数据计算位于GLSurfaceView.Renderer的onSurfaceChanged()方法。下面的代码先取得了GLSurfaceView的高度与宽度,然后使用Matrix.frustumM()方法将数据填充到投影转换的Matrix中。// mMVPMatrix is an abbreviation for "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; // this projection matrix is applied to object coordinates // in the onDrawFrame() method Matrix.frustumM(mProjectionMatrix, 0, -ratio, ratio, -1, 1, 3, 7); }
这些代码会填充投影矩阵:mProjectionMatrix,它可以被用来与相机视图转换整合。
Note: 仅仅将投影转换应用到要绘制的物体上,一般来说是没什么意义的。通常情况下,还必须将相机视图转换也一并应用。这样才能使物体呈现在屏幕上。
定义相机视图
完成相机视图的转换也是图像处理过程的一部分。在下面的代码中,相机视图转换通过Matrix.setLookAtM()方法进行计算,然后将结果整合进原先所计算好的矩阵中。最后被整合完毕的矩阵接着被用来绘制图形。@Override public void onDrawFrame(GL10 unused) { ... // Set the camera position (View matrix) Matrix.setLookAtM(mViewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f); // Calculate the projection and view transformation Matrix.multiplyMM(mMVPMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0); // Draw shape mTriangle.draw(mMVPMatrix); }
应用投影转换及相机转换
为了可以使用上面所整合完毕的矩阵,首先需要将该矩阵变量添加到上节课程所定义的顶点渲染器中:public class Triangle { private final String vertexShaderCode = // This matrix member variable provides a hook to manipulate // the coordinates of the objects that use this vertex shader "uniform mat4 uMVPMatrix;" + "attribute vec4 vPosition;" + "void main() {" + // the matrix must be included as a modifier of gl_Position // Note that the uMVPMatrix factor *must be first* in order // for the matrix multiplication product to be correct. " gl_Position = uMVPMatrix * vPosition;" + "}"; // Use to access and set the view transformation private int mMVPMatrixHandle; ... }
接下来,修改绘制物体对象的draw()方法,以便可以接收整合后的矩阵,然后将其应用到图形中:
public void draw(float[] mvpMatrix) { // pass in the calculated transformation matrix ... // get handle to shape's transformation matrix mMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix"); // Pass the projection and view transformation to the shader GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mvpMatrix, 0); // Draw the triangle GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount); // Disable vertex array GLES20.glDisableVertexAttribArray(mPositionHandle); }
如果有正确的计算结果以及正确的使用了整合后的矩阵,那么图形会以正确的比例被绘制出来,最后看起来的效果应该是这样子的:
现在程序就可以正常显示比例正常的图形了,是时候为图形添加动作了。
相关文章推荐
- Android EventBus源码解析 带你深入理解EventBus
- Android EventBus实战 没听过你就out了
- android-关于圆形头像
- 注册界面设计
- Android Gradle插件用户指南
- Android Studio技巧合集
- Android 热补丁动态修复框架小结
- AndroidStudio 优秀插件汇总
- Android存储使用参考
- 在AndroidStudio中创建java应用 步骤
- 一个帖子学会Android开发四大组件
- Android应用程序打包时,出现错误:"XXX" is not translated in "af" (Afrikaans), "am" (Amharic), "ar" (Arabic).....
- textview设置size 单位
- android中动画的实现
- GitHub Top 100的Android开源库
- Android Studio:Power Save Mode
- Android 自定义View属性相关细节总结
- Android ADB命令的使用
- 沉浸式状态栏的实现--ANDROID – 在 KITKAT 以上版本的 TRANSLUCENT 介紹
- [Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程