术语:
大多数3D工作中,我们参照的依据是欧几里得几何学中的三维空间(X,Y,Z)。但在某些情况下,参照投影几何更适用,除了X,Y,Z分量外,增加一个W分量,这个四维空间叫做“投影空间”,在四维空间中的坐标叫做“齐次坐标”。
为了达到3D软件的目的,“投影的”和“齐次的”可以理解为“4D”。
不是四元数:
虽然四元数跟齐次坐标很像,都是4D矢量,通常用(X,Y,Z,W)来表示,但是,四元数和齐次坐标是不同的概念,使用的领域也不同。
这篇文章跟“四元数”没有一毛钱关系。
类比2D:
了解3D之前,我们先看看2D的投影是怎么回事儿。
想象投影仪在一个屏幕上投影一张2D图片,很容易就可以得到投影图片的X,Y分量。
现在,靠投影仪和屏幕之间,你就可以发现W分量了。
W分量是投影仪倒屏幕的距离。
那么W分量的作用是什么呢?想象一下,如果我们移动投影仪的位置,来增加或减少W分量的值,那么投影出的2D图片会发生什么?如果将投影仪靠近屏幕,2D图片缩小,将投影仪远离屏幕,2D图片放大。没错,这就是W分量的作用。
W分量的值,影响了投影出的2D图片的大小。
应用到3D:
到目前为止,还没有一个3D投影仪,很难想象3D中的投影几何,但是3D下的W分量与2D的作用相同。当W增大,坐标被拉伸,W缩小,坐标被压缩。W对3D坐标做缩放变换。
W=1时:
通常,给3D编程初学者的建议是,无论什么时候将3D坐标转换为4D坐标时,让W=1。原因是,当缩放坐标的W为1时,坐标不会增大或缩小,保持原有的大小。所以,当W=1,不会影响到X,Y,Z分量的值。
因此,当谈论到3D计算机图形学时,当坐标中W=1时被称作“正确”。如果渲染使用W>1的坐标,每一个3D物体看起来都会变大,反之,W<1的坐标中,3D物体会变小;如果渲染时试图让 W=0,即做透视除法时除数为0,那么你的程序会崩溃;如果W<0,每一个物体都会上下水平翻转。
在数学中没有所谓的“不正确”的齐次坐标,使用齐次坐标时让W=1仅仅是用于计算机图形学中的投影转换。
数学原理:
现在,让我们来看一些例子,了解数学原理。
在距屏幕3米远的位置放一个投影仪,投影出一个点(15,21)在2D图像中,相应的投影坐标中的向量为(X,Y,W)=(15,21,3)。
现在,想象推动投影仪向屏幕靠近,直到距离1米,越靠近屏幕投影,投影出的图像越小。投影仪靠近了3倍,因此图像缩小了3倍。如果我们将原向量的X,Y,Z分量都除以3,我们得到一个新向量W=1:
投影出的点在坐标中的新位置(5,7):
这就是怎样将一个“不正确”齐次坐标转换到一个“正确”坐标的方法:所有分量除以W,这个过程对2D和3D同样适用。
通过给向量乘以W的倒数,来实现向量的所有分量除以W,下面是一个4D的例子:
在计算机图形学中使用齐次坐标:
就像开始提到的,针对3D计算机图形学中的有些情况齐次坐标很有用,下面我们来看看这些情况:
3D坐标中的转换矩阵:
旋转和缩放的转换矩阵只需要3列,但是为了处理平移,至少需要4列矩阵,这就是为什么矩阵变换通常用4x4的矩阵。然而,4列矩阵不能与3维向量相乘,只能与4维向量相乘,这就是为什么我们使用齐次的4维向量取代3维向量。
通过齐次坐标处理矩阵变化,第4维W分量通常不用改变。从3D转换到4D,只需将W分量设置为1,并且经过变换矩阵处理后,W分量的值仍为1,这意味着我们忽略W分量即可转换回3D坐标。这个对目前为止大多数矩阵变化都适用,如平移、旋转、缩放。需要注意的例外是投影矩阵会影响W分量。
透视变换
在3D世界中,物体离相机越远看起来越小,这个现象叫做透视。在镜头中,如果猫离相机足够近,远处的大山会比猫看上去小。
在3D计算机图形学中,透视是通过变换矩阵改变向量的W分量来实现的。在变换到观察空间后(对向量应用了观察矩阵)但还没进行投影变换(还没有对向量应用投影矩阵),每个向量的Z分量表示了距离相机的距离。因此,Z分量越大,矢量应该越小。W分量影响这个缩放,所以投影矩阵用Z分量的值改变W分量的值。
在3D计算机图形学中,透视是通过投影矩阵变换,改变每一个向量中W分量的值来实现透视的。
下面来看一个透视例子,通过投影矩阵变换到齐次坐标。
注意投影矩阵是怎样用Z分量改变W分量的。
经过投影矩阵变换后,每一个向量还需要经过“透视除法”。
透视除法只是将齐次坐标中的W分量转换为1的专用名词。
继续上面的例子,透视除法这步如下:
完成透视除法后,W分量就没用了,我们就得到了一个完全符合3D透视投影规则的3D坐标。
设置平行光:
齐次坐标的一个特点是可以有无限远的点(或无限长的向量),在3D坐标中这个是不允许的。当W=0时,这点表示无限远的一个点。如果你尝试将一个W=0的齐次坐标转换为一个普通的W=1的齐次坐标,这会导致4次除以零的操作:
这意味着,不能将W=0的齐次坐标转换为3D坐标。
那这有什么用呢?用处说来就来了,平行光可以认为是一个无限远处的点光源。当一个点光源在无限远的位置,光线就会变成平行的,并且所有光线都在同一方向,这就是平行光的基本定义,想想太阳吧。所以在传统的3D图形中,平行光可以通过改变点光源位置向量中的W分量来表示,当W=1时,是一个点光源,当W=0时,是一个平行光。
在实现光照代码时,这更多的是一种传统的约定,但不是一种有用的方法,因为平行光和点光源的行为不同,通常分开实现。
总结:
齐次坐标有一个额外的维度叫W分量,用来缩放X,Y,Z三个分量的值。平移和透视投影的矩阵变换只能在齐次坐标中适用,所以在3D计算机图形学中它们非常的常见。当W=1时,X,Y,Z分量被称为“正确的”。任何齐次坐标,只要W不为0,都可以通过将每一个分量除以W来转换到W=1的向量。当W=0时,这个坐标表示无穷远的一个点(或者表示无限长的一个向量),通常用于表示平行光的方向。
原文:https://www.tomdalling.com/blog/modern-opengl/explaining-homogenous-coordinates-and-projective-geometry/