运用投影与相机视角

编写: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. django中常见命令总结

    一,创建一个django项目: django-admin.py startproject mysite二,在mysite目录下创建blog应用: python manage.py startapp b ...

  2. SQL学习记录:函数(二)

    字符串函数 1.获取字符的ASCII码 语法结构: ASCII(espression)    这里的expression是一个返回char或varchar数据类型的表达式,ASCII函数仅对表达式最左 ...

  3. MySQL新建数据库时utf8_general_ci编码解释

    utf8_unicode_ci和utf8_general_ci对中英文来说没有实质的差别.utf8_general_ci: 校对速度快,但准确度稍差.utf8_unicode_ci: 准确度高,但校对 ...

  4. codeforces 584E Anton and Ira [想法题]

    题意简述: 给定一个$1$到$n(n<=2000)$的初始排列以及最终排列 我们每次可以选取位置为$i$和$j$的 并交换它们的位置 花费为$ |i-j| $ 求从初始状态变换到末状态所需最小花 ...

  5. spring事务传播行为讲解转载

    https://segmentfault.com/a/1190000013341344 前言 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为.事务传播行为是 ...

  6. mockito测试入门学习

    一.什么是mock测试,什么是mock对象? 先来看看下面这个示例: 从上图可以看出如果我们要对A进行测试,那么就要先把整个依赖树构建出来,也就是BCDE的实例. 一种替代方案就是使用mocks 从图 ...

  7. Mac版-python环境配置(二):编译器pycharm下载安装

    简介 PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试.语法高亮.Project管理.代码跳转.智能提示.自动完成.单元测试.版本 ...

  8. 斯坦福【概率与统计】课程笔记(四):EDA | 茎叶图

    茎叶图的只做方法如下: 将每个数字分成茎和叶 对所有茎排序,并纵向从小到大放置好 对相同茎下的叶归到一起并排序,垂直于茎的排列方向放置好 举个例子:我们有一份奥斯卡影后的年龄集合: 34 34 27 ...

  9. hdu3438 Buy and Resell(优先队列+贪心)

    Buy and Resell Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  10. MVC5使用SignalR进行双向通信 (1)

    @a604572782 2015-08-10 09:01 字数 2133 阅读 1245 MVC5使用SignalR进行双向通信 (1) 配置SignalR 在NuGet中通过 install-pac ...