(转)使用OpenGL显示图像(四)运用投影与相机视角

运用投影与相机视角

编写: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);
}

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

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

原文地址:https://www.cnblogs.com/wangle1001986/p/8361210.html

时间: 2024-11-06 14:40:39

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

Android官方开发文档Training系列课程中文版:OpenGL绘图之应用投影与相机视图

原文地址:http://android.xsoftlab.net/training/graphics/opengl/projection.html##transform 在OpenGL ES环境中,投影相机View可以将所绘制的图形模拟成现实中所看到的物理性状.这种物理模拟是通过改变对象的数字坐标实现的: 投影 - 这基于GLSurfaceView的高宽的坐标转换而实现.如果不采用这种计算,所绘制的对象就会由于窗口的不平等比例所曲解.投影转换只有在OpenGL视图的比例被确定或渲染器的onSur

[转载]详解OpenGL的坐标系、投影和几何变换

详解OpenGL的坐标系.投影和几何变换 转载http://blog.csdn.net/blues1021/article/details/51535398# OPengl的渲染流程是先全部设置好数据和状态,GL_MODELVIEW是将当前要变换的空间向量和模型视图矩阵当前最顶矩阵(会乘以摄像机变换乘投影矩阵的矩阵得最终变换矩阵)关联存储好包括状态设置,提交渲染时候glflush才会提交渲染数据和命令. glPushMatrix()和glPopMatrix()的配对使用目的是方便得到需要变换的最

opencv学习笔记(四)投影

opencv学习笔记(四)投影 任选了一张图片用于测试,图片如下所示: 1 #include <cv.h> 2 #include <highgui.h> 3 using namespace std; 4 using namespace cv; 5 int main() 6 { 7 IplImage * src = cvLoadImage("cat.png", 0); //强制转化读取图像为灰度图 8 cvShowImage("灰度图像", s

OpenGL教程翻译 第十三课 相机空间

OpenGL教程翻译 第十三课 相机空间 原文地址:http://ogldev.atspace.co.uk/(源码请从原文主页下载) Background 在上几节中我们看见两种类型的顶点变换.第一种类型的变换是改变对象的位置(平移),旋转,尺寸(放缩).这些变换允许我们在3D世界中把一个对象放在任何位置.第二种类型的变换是透视投影变换,把在3D世界坐标系下的顶点位置投影到2D世界坐标系下(比如一架飞机).一旦坐标变换为2D坐标,那么非常容易将这些2D坐标映射到屏幕空间坐标.这些坐标实际上被用来

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

1.宽高比问题 我们现在相当熟悉这样一个事实,在OpenGL里,我们要渲染的一切物体都要映射到X轴和Y轴上[-1,1]的范围内,对于Z轴也一样.这个范围内的坐标被称为归一化设备坐标,其独立于屏幕实际尺寸或形状. 不幸的是,因为它们独立于实际的屏幕尺寸,如果直接使用它们,我们就会遇到问题,例如在横屏模式下被压扁的桌子. 假设实际的设备分辨率以像素为单位是1280*720,这在新的Android设备上是一个常用的分辨率.为了使讨论更加容易,让我们也暂时假定OpenGL占用整个显示屏. 如果设备是在竖

OpenGL学习(四) 几何变换

线性变换 仿射变换:包括平移.旋转以及比例变换.这种变换能够保持直线建的平行性,并且可逆. 射影变换:包括透视变换等.由于这些变换都是将三维实体投影到二维空间,所以不可逆. 齐次坐标系     OpenGL实际是在四维坐标中定义的,坐标为(x,y,z,w)在三维点空间上显示为(x/w,y/w,z/w),不定义w的话,w默认为1. 故我们用于建模.观察以及投影的所有变换都可由4*4的矩阵直接作用于齐次坐标系中的点和向量得到. 模型-视图变换和投影变换     每个顶点都经过当前模型-视图矩阵和投影

OpenGL第四节:滚动和矩阵栈

头文件不变 LUtil.h GLfloat gCameraX = 0.f, gCameraY = 0.f;//相机位置 bool initGL(){ glViewport( 0.f, 0.f, SCREEN_WIDTH, SCREEN_HEIGHT ); glMatrixMode( GL_PROJECTION ); glLoadIdentity();//加载投影矩阵为单位矩阵 glOrtho( 0.0, SCREEN_WIDTH, SCREEN_HEIGHT, 0.0, 1.0, -1.0 );

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

转:http://blog.csdn.net/junzia/article/details/52842816 前面几篇博客,我们将了Android中利用OpenGL ES 2.0绘制各种形体,并在上一篇博客中专门讲了GLSL语言.但是我们看到的基于OpenGL开发的应用和游戏,可不仅仅是那些规则形体和一些简单的色彩构成,而是各种不规则的形体构成了现实世界或者卡通世界的人和事物,他们都是外面穿着漂亮“衣服”的.本篇博客就是来讲解这些“衣服”的基础的.这些衣服就是纹理贴图. 什么是纹理贴图 一般说来

地图投影系列介绍(四)----投影坐标系

4.4 我国常用地图投影  我国基本比例尺地形图(1:100万.1:50万.1:25万.1:10万.1:5万.1:2.5万.1:1万.1:5000)除1:100万以外均采用高斯-克吕格Gauss-Kruger投影(横轴等角切圆柱投影,又叫横轴墨卡托Transverse Mercator投影)为地理基础.  1:100万地形图采用兰伯特Lambert投影(正轴等角割圆锥投影),其分幅原则与国际地理学会规定的全球统一使用的国际百万分之一地图投影保持一致.  海上小于50万的地形图多用墨卡托Me