运用投影与相机视角

编写:jdneo - 原文:http://developer.android.com/training/graphics/opengl/projection.html

在OpenGL ES环境中,利用投影和相机视角可以让显示的绘图对象更加酷似于我们用肉眼看到的真实物体。该物理视角的仿真是对绘制对象坐标的进行数学变换实现的:

  • 投影(Projection):这个变换会基于显示它们的GLSurfaceView的长和宽,来调整绘图对象的坐标。如果没有该计算,那么用OpenGL ES绘制的对象会由于其长宽比例和View窗口比例的不一致而发生形变。一个投影变换一般仅当OpenGL View的比例在渲染器的onSurfaceChanged()方法中建立或发生变化时才被计算。关于更多OpenGL ES投影和坐标映射的知识,可以阅读Mapping Coordinates for Drawn Objects
  • 相机视角(Camera View):这个变换会基于一个虚拟相机位置改变绘图对象的坐标。注意到OpenGL ES并没有定义一个实际的相机对象,取而代之的,它提供了一些辅助方法,通过对绘图对象的变换来模拟相机视角。一个相机视角变换可能仅在建立你的GLSurfaceView时计算一次,也可能根据用户的行为或者你的应用的功能进行动态调整。

这节课将解释如何创建一个投影和一个相机视角,并应用它们到GLSurfaceView中的绘制图像上。

定义一个投影

投影变换的数据会在GLSurfaceView.Renderer类的onSurfaceChanged()方法中被计算。下面的代码首先接收GLSurfaceView的高和宽,然后利用它并使用Matrix.frustumM()方法来填充一个投影变换矩阵(Projection Transformation 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,在下一节中,我们可以在onDrawFrame()方法中将它和一个相机视角变换结合起来。

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);
}

应用投影和相机变换

为了使用在之前章节中结合了的相机视角变换和投影变换,我们首先为之前在Triangle类中定义的顶点着色器添加一个Matrix变量:

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);
}

一旦我们正确地计算并应用了投影变换和相机视角变换,我们的图形就会以正确的比例绘制出来,它看上去会像是这样:

现在,应用已经可以通过正确的比例显示图形了,下面就为图形添加一些动画效果吧!

(转)使用OpenGL显示图像(四)运用投影与相机视角的更多相关文章

  1. opencv学习笔记(四)投影

    opencv学习笔记(四)投影 任选了一张图片用于测试,图片如下所示: #include <cv.h> #include <highgui.h> using namespace ...

  2. Android OpenGL ES 开发(五): OpenGL ES 使用投影和相机视图

    OpenGL ES环境允许你以更接近于你眼睛看到的物理对象的方式来显示你绘制的对象.物理查看的模拟是通过对你所绘制的对象的坐标进行数学变换完成的: Projection - 这个变换是基于他们所显示的 ...

  3. (转)使用OpenGL显示图像(五)添加移动

    添加移动 编写:jdneo - 原文:http://developer.android.com/training/graphics/opengl/motion.html 转:http://hukai. ...

  4. (转)使用OpenGL显示图像(三)绘制Shapes

    绘制形状 编写:jdneo - 原文:http://developer.android.com/training/graphics/opengl/draw.html 在定义了使用OpenGL绘制的形状 ...

  5. 【Android Developers Training】 65. 应用投影和相机视图

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  6. Android OpenGL ES(四)----调整屏幕的宽高比

    1.宽高比问题 我们如今相当熟悉这样一个事实,在OpenGL里,我们要渲染的一切物体都要映射到X轴和Y轴上[-1,1]的范围内,对于Z轴也一样.这个范围内的坐标被称为归一化设备坐标,其独立于屏幕实际尺 ...

  7. opengl典型例程立方体投影与地图绘制

    立方体投影 http://www.cnblogs.com/opengl/p/3790450.html 地图绘制 http://www.cnblogs.com/opengl/p/3790354.html

  8. 在Android中使用OpenGL ES开发第(四)节:相机预览

    笔者之前写了三篇Android中使用OpenGL ES入门级的文章,从OpenGL ES的相关概念出发,分析了利用OpenGL ES实现3D绘图的重要的两个步骤:定义形状和绘制形状,简单的绘制了一个三 ...

  9. (转)使用OpenGL显示图像(七)Android OpenGLES2.0——纹理贴图之显示图片

    转:http://blog.csdn.net/junzia/article/details/52842816 前面几篇博客,我们将了Android中利用OpenGL ES 2.0绘制各种形体,并在上一 ...

随机推荐

  1. window安装activemq

    原文: https://www.cnblogs.com/donsenChen/p/8656563.html ActiveMQ5.14.5下载地址 http://activemq.apache.org/ ...

  2. Java程序执行的过程

    ava程序执行的过程: Step1:将字节码加入内存: Step2:对字节码进行合法性检查: Step3:jvm会为每个字节码文件都生成一个对象(class): Step4:执行静态代码块,初始化静态 ...

  3. Java牛角尖【007】:Java中的Error能不能被Catch

      Java牛角尖[007]:Java中的Error能不能被Catch 网上看到很多朋友说Java中Error是无法Catch到的,而Java中定义的Error类型又很难测试到,那就估且以为确是如此吧 ...

  4. docker镜像加速遇见的一个问题

    今天运行docker发现了一个问题,运行docker images会报 Cannot connect to the Docker daemon at unix:///var/run/docker.so ...

  5. mysql linux下安装部署

    一.安装简介 用户名:mysql安装目录:/usr/local/mysql-5.5数据库目录:/data/mysql/data源码包:mysql-5.5.28.tar.gz 二.安装准备 a.vi / ...

  6. Mutable and Immutable Variables in Python

    本文解决python中比较令人困惑的一个小问题:传递到函数中的参数若在函数中进行了重新赋值,对于函数外的原变量有何影响.看一个小栗子: def fun(a): a=2 return a=1 fun(a ...

  7. mysql 查看数据库最大连接数

    show variables like '%max_connections%'; navicat 切换到命令行: navicat查看建表语句: 选中表,右键,对象信息,选择DDL

  8. input只读效果

    有两种方式可以实现input的只读效果:disabled 和 readonly. 自然两种出来的效果都是只能读取不能编辑,可是两者有很大不同. Disabled说明该input无效,及其value不会 ...

  9. Git文件操作命令

    添加文件 git add 添加指定文件: git add test.txt Test.java 添加所有文件: git add . 取消添加文件 git reset HEAD – filename g ...

  10. 插件化框架解读之Class文件与Dex文件的结构(一)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 Class文件 Class文件是Java虚拟机定义并被其所识别的 ...