【渲染管线-1】坐标变换的理解

本文将尽可能细致的对坐标变换的过程,用意和一些细节进行剖析,目的是方便自己在遗忘时进行复习,因此可能会有些繁琐。

文章将分成两部分,第一部分包含大量例子,主要用于对变换过程有一个形象的概念,不涉及具体内部计算,第二部分为真实计算逻辑,但隐去了计算的公式,有时间会补充第三部分即计算过程。

1、对坐标变换的形象理解

一个点,从三维空间到最终映射到屏幕上,它经历了一系列的坐标变换以及颜色的计算,这里只说坐标变换。

举例,若你的桌子右上角有一个杯子,以前为z,右为x,上为y,那么它的坐标在(1,0,1),杯子的把手可能在(1,0.5,1)但是,对杯子自己来说,在杯子的认知里,它在(0,0,0)这个点,它的把手在(0,0.5,0)。

现在,移动视线从不同的位置去看这个杯子,它在你的视野里可能位于右下,左上,正中间等等。这时,在你的视野里,杯子的位置坐标将不再是(1,0,1),例如,当视线与桌子齐平,并正视杯子时,那么杯子在你的正前方1个单位处,它的坐标是(0,0,1)。

以上所述即为坐标变换过程,即,给定杯子,桌子与人眼的基向量,并给定杯子在自身模型空间内的坐标点,则可通过坐标变换计算出该点在人眼中的坐标。

实际上,在3D场景内,也有一个代替人眼的对象,叫摄像机,所展现出的画面均以摄像机所“看”为准,因此,在计算机内,也要经历这样的一个坐标变换过程。

然而,为何一定要经历这样的变换来获得最终坐标呢?因为,通常来说,模型中顶点的坐标位置都是基于模型空间的,根本无法不通过变换而直接得知一个点在摄像空间里的坐标,这跟人眼看过去就可以进行直接进行位置判断有本质的区别,因此,在计算机的3维世界内,我们不得不借用数学工具,来对点的最终位置进行计算。

这里具体展开说基向量的变换,因为它是整个坐标变换的核心概念。

基的作用就是赋予点“坐标”,同一个点基于不同的基即有了不同的坐标,因此,进行坐标变换,本质上就是进行基向量的变换。

说的再简单一点,基就像单位,(1,2)即为该点由1个单位的x与2个单位的y组成,且,由1个单位的x,与2个单位的y,在x与y这两个基不变的情况下,可唯一定位一个2维空间内的一个点。为啥要把一个点分成两个单位来描述?因为两个不平行的向量可确定一个唯一的二维空间(二维平面)…

因此,基向量的变换,就可理解为换一组单位去描述这个点。

生活中进行单位的换算,首先就是计算1个单位=多少个新单位,例如1元=10角,那么10元=10*10角。因此,1个单位的x与2个单位的y也是这样进行换算的。

以二维空间为例,如下图所示,将黑色坐标轴与红色坐标轴按原点进行重合,则,红色的1个x单位,等价于 根2/2 个黑色的x+根2/2 个黑色的y。

将y也按照如此进行计算,即可完成单位的转换,即基的变换,再将1个x与2个y的系数1和2乘进去,就可以得出该点在进行了基向量的变换以后的坐标。

但是!要注意,我们在最初是将两个坐标系的原点通过移动进行了重合,因此,最终计算出的坐标需要再移动回去即可。
在这里插入图片描述

2、整个过程在计算机内的逻辑

首先世界坐标是固定不变的,且无法人为设置,一般的引擎都具有add scene之类的api,在这个scene内默认自带一个世界坐标,三根轴的方向通常是右x,上y,以及垂直于屏幕向外是z。

这个默认的坐标就是最初的“单位”,必须拥有最初的单位,才能在后续添加/计算其他的基。

在scene内添加一个节点,这个节点也可以理解为是一个新的坐标系,刚添加进去时,节点内储存的该节点的基与世界坐标系的基是一样的,即(1,0,0),(0,1,0),(0,0,1),在这之后,通过移动,旋转该节点,它内部储存的基也会进行相应的变化,此外,因为它的初始基是世界坐标系,所以四舍五入变化也是基于世界坐标。

此时,在该节点内再添加一个新的节点,则这个新的节点又将拥有一个默认的基,这个基也是(1,0,0),(0,1,0),(0,0,1),但此时,这个基是基于它父节点的基进行计算的。

综上,这个父子关系可抽象为 scene–>A节点–>B节点,此时,若B节点内有一个顶点xyz,则该顶点的坐标,在A的基向量下的坐标(即变换到A的坐标系尺度内),其计算方法是乘以B节点内储存的基向量所组成的变换矩阵,因为B节点内储存的基,就是基于A坐标系而计算的。

此外,这里也可以解释为什么节点A内的节点B的默认基也是(1,0,0),(0,1,0),(0,0,1),因为,如果它的默认基是A节点的基,则B的基就也是基于世界坐标系了,那么,B节点内的顶点,通过B储存的基进行变换后,就直接变换到世界坐标系了,而不是变换到它的上一层A节点的坐标系。

上述问题会导致,如果我们希望B节点内的一个顶点,基于A节点的原点进行某些运动,这显然需要我们知道该顶点在A坐标系下的坐标,因此,如果B内的顶点基于B储存的基进行变换后直接变换到了世界坐标系下,那就无法基于A的原点进行运动了,这显然不是我们希望的。

但是!由于在实际运行时,从顶点到世界再到摄像机,这一条的变换是最频繁的,因此,通常一个节点内除了储存模型基以外,还会储存世界基,也就是它的基,基于世界坐标的值,根据不同的需求,就可以挑选不同的基(大部分情况下引擎会贴心的将其组装成变换矩阵进行储存)进行变换计算了。

因此,通过这样的父子关系,并且给每个节点(节点也可理解为坐标系)时刻储存着它基于父节点的基以及原点位置(一般是position这个属性),这样,就可以随时将某个基下的一个顶点坐标,通过层层变换,最终回归到该结构的根坐标系——世界坐标。

当然,因为从A变换到B,与从B变换到A没什么本质上的不同,因此,也可以随时从根变换到其他的坐标系。

因此,显而易见,在将一个包含多个层级的节点内的某个顶点坐标,通过层层变换,得到该顶点在世界坐标系内的坐标后,也可以继续变换到摄像机坐标系内,但是!这里要万分注意一件事,那就是变换到摄像机的坐标系,这里涉及到一个逆变换的问题,如下图:
在这里插入图片描述
如图,从左臂依次往上,每个节点内都储存着该节点的本地坐标系在父节点的坐标系内的表示,也即变换到父节点空间的变换矩阵,因此,左臂x左臂内所存矩阵x躯干矩阵x角色矩阵,即可将左臂的节点变换到世界坐标系,但是,在变换到摄像机空间时,不可直接x摄像机节点内所存的矩阵,因为这个矩阵也是基于世界空间的,而需要x的是世界坐标系在摄像机下的变换矩阵,即摄像机到世界空间的变换矩阵的逆矩阵!

有点绕哈,其实很好理解,如下图,我们需要顺着箭头走到摄像机节点,但是根节点到摄像机的箭头是反着的,于是需要对矩阵取逆,就这么简单…
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值