【Unity Shader学习笔记】Unity中使用的坐标系及变换过程
文章目录
Unity中使用的坐标系及变换过程
概述
一个点从三维空间到被绘制到二维空间大致需要经历以下几个步骤:
- 模型空间(局部空间)
- 世界空间
- 摄影机 观察空间
- 剪裁空间
- NDC
- 屏幕空间
看书的时候虽然觉得看懂了,但是后来发现还是没有记住,因此特地写下来,当是为书作注,也加上一些自己的理解。主要参考冯乐乐的Unity Shader入门精要第四章第六节和第九节。
另外还参考了:
https://blog.****.net/ad88282284/article/details/78245719
https://learnopengl-cn.github.io/01 Getting started/08 Coordinate Systems/
模型空间坐标,世界空间坐标,观察空间坐标
我们知道所谓坐标不过是相对于参考系而言的一种定位方式,因此上述三种坐标的本质是一样的,都是三维空间内某个物体相对于另一个物体的向量表达。
具体的细节不过赘述,这里只表达一下个人的理解,帮助读者(包括我自己)梳理一下。
这三个坐标是不触及真正的“把物体转化到屏幕上”的过程的。
这三个空间唯一的不同就是原点坐标以及原点坐标轴方向有所不同,但本质是一样的。因此三个坐标系之间两两转换无非是这个过程:
在模型空间到世界空间时,模型空间是坐标B,世界空间是坐标A
在世界空间到观察空间时,世界空间是坐标B,观察空间是坐标A
从观察空间到剪裁空间
概述
这一步利用视锥体对观察空间内的坐标进行剪切,这里讲解比较复杂而常用的透视投影,正交投影过程较为简单。
为了达到这个目的,首先通过透视投影,将观察空间下的点坐标进行一个线性的变换。
这时,通过一个简单的式子:用某点坐标的XYZ分量和W分量作比较,就能决定图元是否被绘制
透视投影
视锥是一个四棱台,包含六个平面,其中两个平行面分别是近剪裁平面和远剪裁平面:
注意到这里Z轴是指向摄像机的反方向的,这里采用的是右手系。
观察空间的视锥体根据不同的视场(field of view,FOV),宽高比(Aspect),近剪裁平面距离(Near),远剪裁平面距离(Far),形态可以多种多样,根据这些值,我们可以算出视锥内某个点在观察空间下的坐标范围:
由于采取的是右手系,这里z是负值
为了剪裁方便,进行如下变换:
这一步矩阵变换可视为两次缩放:
第一次缩放是针对xy分量:
使得xy分量不受FOV和Aspect变量的影响,直观上看起来就是x和y分量都只跟与摄像机的距离有关系,即这一步使得视锥的边缘跟z轴是成45度角的。
因此这时候FOV看起来是90度
第二次缩放是针对z深度的缩放:
首先将z轴整体翻转了过来,并且将整个视锥的深度范围变成(-Near,Far)的范围。然后再将坐标整体后移,使得视锥包含摄像机。并且用w分量保存原本变换之前的z值的负值。
不难得到变化后,该点在剪裁空间下的坐标范围:
剪裁
到这里已经很直观了,如果这时候吧xyz分量除以一个w分量,这个视锥就自然而然地变成了一个立方体。
而剪裁的时候也非常简单:
只要把每个分量取绝对值跟w分量比较,一旦超出,则该点位置的图元就要被舍弃。
这里再解释一下z分量吧,在xyz三个分两种,我们可以看到xy的坐标范围都是实际上直接跟w值已经挂钩了,超出这个范围就不是视锥内的,因此也很好理解,但是z分量则不同。
简单分类讨论一下为什么z分量绝对值超过w就意味着超出视锥范围:
首先前提是,这里的w分量实际上就是原本的z值,而当前的z值是由原本z值做线性变换而来的,这意味着当前zw分量有如下关系:
因此,z和w必然是一一对应的,那么当|z|>w,即意味着z>0时,z>w或者z<0时,-z>w。而上述范围实际上已经对应了这个关系:
从剪裁空间到屏幕空间
概述
剪裁空间得到的视锥,已经能方便的剪裁不需要的图元,但是为了转化到屏幕上,还要先经过齐次除法得到NDC(Normalized Device Coordinate,归一化的设备坐标),然后使用NDC下的xy分量,根据实际屏幕大小来进行缩放。得到实际屏幕的2D坐标。
齐次除法得到NDC
上面其实已经提到,用剪裁空间下的坐标中的xyz分量除以w分量就得到了NDC坐标。
NDC或剪裁空间到屏幕空间的转换
可以看到NDC下有,因此,为了映射到需要做如下映射:
如果是直接从剪裁空间要得到屏幕空间的话: