顶点的坐标空间变换过程(都是以Unity中的坐标空间为准)
1、模型空间(model space)
模型空间有时也被称为对象空间(object space),或局部空间(local space),是模型本身自己的坐标空间,这个是在美术人员建模的时候决定好的,如模型的中心点
2、世界空间(world space)(左手坐标系)
世界空间被用于描述绝对位置。
顶点变换的第一步就是将顶点从模型空间变换到世界空间,这一步变换通常叫做模型变换(model transform),一般是经过缩放,旋转,平移这几步,将模型转换到世界坐标系下。(TRS)
3、观察空间(view space)(右手坐标系)
观察空间也被称为摄像机空间(camera space)。摄像机决定了游戏渲染使用的视角。在观察空间中,摄像机位于原点,+Z轴指向的是摄像机的后方。
顶点的第二步变换就是将顶点从世界空间变换到观察空间,这一步变换通常叫做观察变换(view transform)。
因为世界空间(world space)和观察空间(view space)是两个不同的坐标系,所以就涉及到坐标系的转换。有两种方法,一是利用之前我们说过的坐标系转换,求出世界空间到观察空间的矩阵(先求得观察空间到世界空间的矩阵,然后求其逆矩阵,因为我们得知摄像机在世界坐标空间下的原点位置以及坐标轴的表示)。第二种方法就是通过平移整个观察空间,我们可以现将摄像机看作是一个在世界空间下的一个物体,通常需要经过缩放,旋转,平移将物体转换到世界空间下,那么我们就通过逆向操作,即平移,旋转,缩放,求得矩阵。
例如:
坐世界空间下,摄像机的pos(0,10,-10),rotate(30,0,0),那么我们就可以通过pos(0,-10,10),rotate(-30,0,0)来求得矩阵。因为是逆向操作,所以是先平移,然后旋转,因为在观察空间下使用了右手坐标系,所以最后求得的矩阵中还要将Z值取反。
Z轴取反
最后求得的矩阵就可以用来将世界空间下的点转换到观察空间下。
4、裁剪空间(clip space)
裁剪空间也被称为齐次裁剪空间,这个用于转换的矩阵叫做裁剪矩阵(clip matrix),也被称为投影矩阵(projection matrix)。
裁剪空间存在的目的就是就快速的对要渲染的图元进行裁剪:完全位于裁剪空间内的会被保留,完全在裁剪空间外的会被裁剪掉,与裁剪空间重叠的会被裁剪掉。
如何决定这个裁剪空间:视椎体(view frustum)
视椎体由六个裁剪平面(clip plane)包围而成,视椎体有两种类型:透视投影(perspective projection),正交投影(orthographic projection)。
在视椎体中,有两个面比较特殊:近裁剪平面(near clip plane),远裁剪平面(far clip plane),这两个面决定了摄像机能看见到的深度范围。
因为直接使用视椎体定义的空间不是很方便进行裁剪,所以就需要把顶点转换到裁剪空间,即使用投影矩阵。
什么是投影:就是一个降维的操作,如将三维空间转换到二维空间坐标下。
投影矩阵的作用:
(1)首先是为投影做准备,虽然叫做投影矩阵,但实际是没有进行投影操作的,真正的投影操作是经过齐次除法(homogeneous division)。而经过投影矩阵变换之后,顶点的w分量具有特殊意义。
(2)其次是对x,y,z分量进行缩放,因为直接使用视椎体的六个平面进行裁剪比较麻烦,所以经过投影的缩放之后,就可以直接使用w分量作为一个范围值,只要x,y,z都在这个范围内,就说明这个点位于裁剪空间内。
所以w分量经过投影矩阵之后会有更丰富的含义。
透视投影:
(1)透视投影的6个裁剪平面由近、远裁剪平面,FOV(field of view),视口纵横比(aspect)决定,即视口宽高比。在Unity中纵横比由Game视图的纵横比和Viewport Rect中的W,H共同决定。
image.png
近、远裁剪平面高度
(2)然后根据Near,Far,FOV,Aspect可以确定投影矩阵
投影矩阵
注:此为Unity下的坐标系,观察坐标为右手坐标系,使用列矩阵在矩阵右侧相乘,变换之后的W分量范围在[-W,W]之间。
(3)一个顶点和投影矩阵相乘之后,就可以有观察空间变换到裁剪空间
顶点变换
从相乘的结果来看,其实就是对X,Y,Z分量分别进行了缩放,Z分量还进行了位移。缩放的目的是为了方便裁剪,此时W分量不在是1,而是Z分量取反之后的结果。
现在就可以对顶点就行裁剪了:
不等式
只要相乘之后的结果满足上述不等式,则说明此顶点不会被裁剪。
image.png
也可以发现,裁剪矩阵改变了空间的旋向性,空间的Z坐标方向反过来了,变换成了左手坐标系,z值越大离摄像机越远。
正交投影
(1)使用正交投影变换之后的顶点,W分量仍然是1,因为正交投影矩阵和透视投影矩阵的最后一行不一样
正交投影
正交投影变换
所以顶点变换的第三步就是从观察空间变换到裁剪空间
第四步进行裁剪
4、屏幕空间(screen space)
在裁剪空间进行完所有裁剪之后,就是要进行真正的投影操作了,即把视椎体投影到屏幕空间中。经过真正的投影变换,得到的结果就是屏幕中真正的像素位置。
而屏幕空间是一个二维空间,为了把顶点从裁剪空间投影到屏幕空间(生成对应的2D坐标),我们需要经过两个步骤:
(1)齐次除法(homogeneous division),也叫透视除法(perspective division),即用齐次坐标系下的x,y,z分量除以w分量,这一步得到的坐标叫做归一化的设备坐标(Normalized Device Coordinates,NDC)(OpenGL)。经过齐次除法(透视除法),裁剪空间被转换到NDC中,就是一个立方体内。在OpenGL中,这个立方体的x,y,z分量范围都是[-1,1]。
对于正交投影,它的裁剪空间其实已经是一个立方体了,而且w分量为1,所以齐次除法对于正交投影并不会产生影响。
正交投影---齐次除法
(2)屏幕映射,经过齐次除法之后,透视投影视椎体和正交投影视椎体都变换到了一个相同的立方体内,然后就可以根据x,y值进行屏幕映射。
在Unity中,左下角为原点(0,0),右上角为最大点(pixelW,pixelH),而变换之后的NDC下的坐标都是在[-1,1]之间,所以要对坐标系进行缩放和平移,总结就是:
齐次除法+屏幕映射
(这个变换式子其实不是很好理解,我们可以提取公因式,而为什么要除以2,因为坐标的范围是[-1,1],1-(-1)=2),其实就是先变换到(0,2)之间也就是X+1,然后再乘像素宽高,因为变换到了(0,2)相当于多加了一个宽高,所以要除以2!
而Z值一般用于深度缓冲。
在Unity中,从裁剪空间到屏幕空间的转换是由Unity完成的,我们的顶点着色器只需要把顶点转换到裁剪空间即可
5、总体流程
总体流程6、法线变换
法线(normal)又被称为法矢量(normal vector),是一种需要特殊处理的方向矢量,法线用于在片元着色器中计算光照。大部分方向矢量都可以使用同一个变换矩阵从A空间变换到B空间中,但是法线可能就会在变换中产生错误,导致不垂直与原来的面,如进行了不等比例的缩放:
为了保持垂直性,我们需要通过切线(tangent),也被称为切矢量(tangent vector),推导出正确的转换法线的矩阵。切线也是模型携带的一种信息,通常与纹理空间对其,并且与法线方向垂直。切线由两个点的插值计算得到,所以可以直接使用变换矩阵对切线变换。由于是矢量,所以平移并不会改变矢量的方向,所以只要使用3X3的矩阵就可以描述清楚矩阵的变换,根据矢量垂直性可推导如下公式:
image.png
其中M矩阵是正常的变换矩阵,G是变换法线N的矩阵
image.png
两向量垂直说明两向量点乘为0,我们可以把两向量看作为一个1X3的矩阵和3X1的矩阵,得出的是一个1X1的矩阵,和实际点乘结果一样,所以T的转置乘N等于0,为了让这个等式成立,则M的转置乘G必须为单位矢量I才可以,所以:
image.png
image.png
从而得出对法线正确的变换矩阵。
如果变换矩阵M是正交矩阵,我们只需要使用原矩阵就能变换法线(只包含旋转):
image.png
如果只包含旋转和统一的缩放系数:
image.png 、如果包含非统一的缩放系数则需要求解逆矩阵才可以。
网友评论