unity 2d摄像机类型_Unity中常用矩阵的推导

在上一篇专栏中涉及了不少Unity中坐标空间变换的内容,因为数学不好,所以特地撰写一篇文章补一下,从头推导Unity Shader中那些常用的矩阵。

线性变换

3D CG中常用的四维向量通常由一个三维的向量

和齐次坐标
组成。为什么要这么做呢,这就涉及到线性变换和仿射变换。

形如

的变换,被称为
线性变换。旋转和缩放都是线性变换。

缩放

对于三维空间的一个点

而言,将其缩放
倍的矩阵如下:

绕坐标轴的旋转

Unity使用的是左手坐标系,因此也以左手坐标系进行推导。判断是左手坐标系还是右手坐标系的方法很简单,我们都假设

轴正向朝上,而
轴正向朝右,则左手坐标系中
轴正向朝屏幕里,右手坐标系反之。

左手坐标系的旋转方向如左手所示,拇指指向绕轴的正向,四指自然弯曲,即旋转的正方向。

先从2D坐标系看,如下图所示,

因此有:

将其展开:

带入

有:

如果写成矩阵形式就是:

这里推出的2D情形,显然可以被视为是绕

轴发生的旋转,因此推广一下,绕
轴旋转
的矩阵变换为:

其他绕坐标轴的矩阵也可推知:

我们知道矩阵运算不满足乘法交换律,因此有必要明确旋转的顺序。在Unity的Transform.Rotate文档中指明:

Applies a rotation of eulerAngles.z degrees around the z axis, eulerAngles.x degrees around the x axis, and eulerAngles.y degrees around the y axis (in that order).

即先绕

轴旋转,其次是
轴,
轴最后。写成运算形式则为:

绕任意轴的旋转

这里不考虑平移,假定所绕轴过原点,且单位向量为

,需要旋转的向量为
,将
分解为垂直于
的分量
和平行于
的分量
,旋转后的向量
也是如法炮制:

v2-eb0ca59088a3d5d6f4e07b603564f519_b.jpg

垂直于
所在的平面。于是有:

可见,

实际上均处于一个平面,且
,可以视作2D空间坐标系下的一对基向量,那么由之前2D旋转向量的经验,可知:

,故:

目前仅仅得出一个式子,而没有矩阵

的表达形式怎么办?当然是捏出基向量扔进去了,以旋转前的基向量
带入上式,有:

众所周知,向量也可以写成列矩阵的形式,将三个基向量旋转之后的列矩阵合并,即可得

仿射变换

平移并不是线性变换,因为

不满足
,因此,为了统一,提出了仿射变换,引入了齐次坐标
,使用高维的线性变换来表示低维的仿射变换。形如
的变换,被称为
仿射变换。仿射变换是指线性变换后接着进行平移操作。

平移

上述给出的缩放和旋转矩阵,只是3x3的部分。平移矩阵的将使用到矩阵的第四列:

模型空间转世界空间

从模型空间转换到世界空间需要考虑Transform的父子关系问题。先不考虑父子关系,则依循先缩放、在旋转、最后平移的原则,模型空间的某点应当以如下方式换算:

如果Transform仍有父亲,则继续按照如上原则计算,直至抵达世界空间。

世界空间转视口空间

我习惯称呼为视口空间,实际上也可以叫观察空间(view space)或者摄像机空间(camera space),指的是相机进行观察的特殊模型空间。Unity的相机空间是右手坐标系。

这一块的计算与模型空间转世界空间恰好相反,要将摄像机作为世界的原点,操作顺序反转的同时,旋转顺序也变成了

,当然因为从左手到右手的缘故,最后不要忘了对
轴分量取反。

视口空间转裁剪空间

众所周知,Camera有正交和透视两种模式,这两种模式最大的区别就在于视锥体的不同,一个是长方体,一个是平头四棱锥。裁剪空间是左手坐标系,这个矩阵可以通过Camera.projectionMatrix拿到。

视锥体可以用六个参数表示,分别是视锥体的六个面,简写成:

。在完成转换后,
范围内将被映射成
,其他面也是一样,参考上一篇专栏给出的视口-裁剪转换后的边界表:

v2-0527f5dbbacbe60f5d72b43631e2a0b6_b.jpg

透视投影矩阵

既然是投影,那么必然存在着降维:令视口空间内存在某点

,在映射到近截面后其坐标为
,因为是投影到近截面,则
分量必然已经确定。根据三角形相似的定理,可知:

注意此处仍是视口空间,右手坐标系,故

分量取反。以
分量为例,若要映射到
上,则映射后的
有:

同理:

带入根据相似三角形计算的值:

同理:

这里的

项,明显可以看出作为
的前两行的内容。于是可以构成如下的内容:

有必要明确一下,

是映射前视口空间内的坐标,
是映射后在视口空间内的坐标
才是映射后裁剪空间内的坐标,
是做了齐次除法后的坐标。

在上述矩阵中,

被我们是做齐次除法的一部分,因此
。另外,我们知道
分量的变换与
无关(这是显而易见的),所以只剩下两个未知量要计算了。在视口空间中,
,因此:

得到了一个方程之后,我们取两个边界解

带入其中:

最后,透视投影矩阵

考虑到视口空间中的视锥体都是关于

轴和
轴对称的,所以可以写成:

实际上我们对Camera的控制并没有到直接设置六个面的程度,那样既不方便,也不够直观,相反我们使用以下3个参数Viewport Rect、FOV、Clipping Plane,Viewport Rect的W和H共同决定了aspect,

,Clipping Plane里已经可以控制
,于是用如下方法计算高度:

宽度就更简单了:

于是,矩阵可做如下表达:

正交投影矩阵

对于正交投影而言,就更简单,直接做线性映射就行,以

为例:

其他分量如法炮制成:

可以看到,相对于透视投影矩阵而言,正交投影矩阵进行了整体的缩放和平移;而透视投影矩阵在各分量上缩放程度不同,还将

放到了齐次除法来做。这点后面说。

裁剪

这时GPU就可以根据矩阵运算后的结果来决定一个片元是否应该被裁剪了,如果一个顶点在视锥体内,则变换后的坐标必须满足:

这是显而易见的,因为无论是透视投影还是正交投影我们推导的时候就要求映射到

上,不在这范围内的肯定是应该被裁剪的。这里用
而不是
作为判断的范围,主要是此时拿到的clip space坐标,如果是透视投影的话,还没进行齐次除法。

裁剪空间投影到屏幕空间

裁剪之后,将三维坐标映射到二维空间中,进行真正的投影。首先做齐次除法,拿到归一化的设备坐标。进行完这一步后,无论是透视投影还是正交投影,裁剪空间都被变换成了一个三个轴向上范围都是

的立方体。

其次将设备参数考虑进去,把

映射到整个屏幕,对于Unity来说,左下角是
,右上角是
,这一步Unity帮我们解决了,顶点着色器里只需要转换到裁剪空间,对对对,就是那个经常搞的UNITY_MATRIX_MVP(后面换成了UnityObjectToClipPos)。

参考文献

【1】计算机图形学之四维齐次坐标 - J1ac - 博客园

【2】软渲染器Soft Renderer:3D数学篇

【3】《Unity Shader入门精要》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity2D运动摄像机是指在Unity引擎使用的2D场景摄像机运动控制组件。摄像机在游戏开发起到非常重要的作用,它可以控制游戏画面的视角和跟随目标物体的移动。在Unity2D,通过使用摄像机组件的属性和方法可以实现不同的运动效果。 首先,可以通过设置摄像机的位置和旋转属性来控制摄像机的基本位置和角度。这可以通过代码编写或者在Unity编辑器进行属性设置来完成。摄像机的位置属性决定了摄像机所拍摄的画面位置,旋转属性则通过调整摄像机的角度来实现视角的变化。 其次,可以通过编写代码来实现摄像机的运动效果。例如,可以使用Lerp方法来实现平滑跟随目标物体的移动。Lerp方法可以使摄像机的位置逐渐接近目标物体的位置,从而实现平滑的跟随效果。 除了跟随移动,还可以实现摄像机的缩放效果。摄像机的Size属性可以控制摄像机视野的大小,通过改变Size的值可以实现画面的缩放效果。 此外,还可以通过编写代码来实现摄像机的抖动效果。通过在摄像机的位置上加入随机的微小偏移,可以模拟出抖动的效果,增加游戏的动态感。 总之,Unity2D运动摄像机是在2D游戏开发非常常用的组件,通过调整摄像机的位置、旋转、缩放等属性以及使用代码控制摄像机的运动,可以实现丰富多样的视觉效果,提升游戏的可玩性和观赏性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值