3D开发知识-投影及各种变换

3D 应用程序开发中,一项很重要的工作是对场景中的物体进行各种投影与变换。相比于OpenGL ES 1.x 的封闭模式,OpenGL ES 2.0 在变换方面采取了开放模式,其 API 中不再提供完成各种变换的方法,变换所用的矩阵都由开发人员直接提供给渲染管线。

因此,基于OpenGL ES 2.0 进行投影与变换的开发时,可能需要了解更多的数学知识。这样虽然增加了开发的难度,但是大大提高了开发的灵活性,下面将对投影与变换相关的数学知识及具体的实现方法进行详细介绍。

一、摄像机的位置
从经验可以了解到,随着摄像机的位置、姿态的不同,就算是对同一个场景进行拍摄,得到的画面也是截然不同的。因此,摄像机的位置、姿态在OpenGL ES 2.0 应用程序开发中就显得非常重要,所以在介绍两种投影与变换之前,首先需要介绍一下摄像机的设置方法。

摄像机的设置主要需要给出3个方面的信息,包括摄像机的位置、观察的方向以及 up 方向,具体情况如下图:
这里写图片描述
(1)摄像机的位置很容易理解,用其在3D空间中的坐标来表示。
(2)摄像机观察的方向可以理解为摄像机镜头的指向,用一个观察目标点来表示(通过摄像机位置与观察目标点可以确定一个向量,此向量即代表了摄像机观察的方向)。
(3)摄像机的 up 方向可以理解为摄像机顶端的指向,用一个向量来表示。
通过摄像机拍摄场景与人眼观察现实世界很类似,因此,通过人眼对现实世界观察的切身感受可以帮助读者理解摄像机的各个参数,如下图所示:
这里写图片描述
从图中可以看出,摄像机的位置、朝向、up 方向可以有很多种不同的组合。例如,同样的位置可以有不同的朝向、不同的 up 方向;不同的位置也可以具有相同的朝向、相同的 up 方向等。
案例中通过调用 Matrix 类的 setLookAtM 方法来完成对摄像机的设置,基本代码如下:

Matrix.setLookAtM(
                mVMatrix, // 存储生产矩阵元素的 float[] 类型数组
                0, // 填充起始偏移量
                cx, cy, cz, // 摄像机的位置x,y,z坐标
                tx, ty, tz, // 观察目标点 x,y,z坐标
                upx, upy, upz // up向量在x,y,z坐标
        );

说明:从上述代码中可以看出,setLookAtM 方法的功能根据接收的9个摄像机相关参数产生摄像机的观察矩阵,并将矩阵的元素填充到指定的数组中。之所以产生矩阵是因为OpenGL ES 2.0 渲染管线的需要。

二、两种投影方式
我们知道,在图元装配之后的光栅化阶段前,首选需要把虚拟3D世界中的物体投影到二维平面上。OpenGL ES 2.0 中常用的投影模式有两种,分别为正交投影透视投影,下面将对这两种投影方式进行详细的介绍。

1、正交投影
OpenGL ES 2.0 中,根据应用程序中提供投影矩阵,管线会确定一个可视空间区域,称为视景体。视景体是由6个平面确定的,这6个平面分别为:上平面(up)、下平面(down)、左平面(left)、右平面(right)、远平面(far)、近平面(near)。
场景中处于视景体内的物体会被投影到近平面上(视景体外的物体将被裁减掉),然后再将近平面上投影出的内容映射到屏幕上的视口中。对于正交投影而言,视景体及近平面的情况如下图:
这里写图片描述
说明:视点为摄像机的位置;离视点较近(距离为near),垂直于观察方向向量的平面为近平面,离视点较远(距离为far)垂直于观察方向向量的平面为远平面。与观察向量平行,从上下左右4个方向约束视景体范围的4个平面分别为上平面、下平面、左平面、右平面,这4个平面与视景体中心轴线的距离分别为top、bottom、left、right。

从上图中可以看出,由于正交投影是平行投影的一种,其投影线(物体的顶点与近平面上投影点的连线)是平行的。故其视景体为长方体,投影到平面上的图形不会产生真实世界中“近大远小”的效果,下图更清楚地说明了这个问题。

正交投影不产生“近大远小”效果的原理图:
正交投影不产生“近大远小”效果的原理图

案例中通过调用 Matrix 类的 orthoM 方法完成对正交投影的设置,基本代码如下:

        Matrix.orthoM(
                mProjMatrix, // 存储生成矩阵元素的float[ ]类型数组
                0, // 填充起始偏移量
                left, right, // near 面的 left、right
                bottom, top, // near 面的 bottom, top
                near, far // near 面 、far面与视点的距离
        );
  • orthoM 方法的功能为根据接收的6个正交投影相关参数产生正交投影矩阵,并将矩阵的元素填充到指定的数组中。
  • 参数 left、right 为近平面左右侧边对应的x坐标,bottom、top 为近平面上下侧边对应的y坐标,分别用来确定左平面、右平面、上平面的位置。参数near、far 分别为视景体近平面与远平面距视点的距离。

前面提到过,场景中的物体投影到近平面后,最终会映射到显示屏上的视口中。视口也就是显示屏上指定的矩形区域,通过如下代码进行设置。

GLES20.glViewport(x,y,width,height); //设置视口

代码中参数x,y为视口矩形左下侧点在视口用屏幕坐标内的坐标,width,height为视口的宽度与高度,具体情况如下图所示。
这里写图片描述
需要注意的是,视口用屏幕坐标系的原点并不在屏幕的左上角,而是位于屏幕的左下角。同时,此坐标系中 x 轴向右,y轴向上,这都与普通 2D 屏幕坐标系有所不同(普通 2D 屏幕坐标系中原点位于左上角,x 轴向右,y轴向下)。

另外,如果应用程序中用于渲染 3D 场景的 GLSurfaceView 类或其子类的对象并不占用整个屏幕的空间,则视口用屏幕坐标系的原点为用于渲染3D场景的GLSurfaceView 类或其子类对象所占屏幕中矩形区域的左下角。

提示:从近平面到视口的映射是由渲染管线自动完成的。一般情况下,应该保证近平面的宽高比与视口的宽高比相同,也就是满足“(left+right)/(top+bottom)== width/height”,否则显示在屏幕上的图像会拉伸变形。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值