3D几何学
直线
通过点,走向与方向平行的直线可表示为
从点到直线的距离等于
设直线方向为,则判断两条直线平行的条件是:
平面
法向量为并包含点的平面表达式为
其中,。平面也可以表示成,其中为四维坐标,为坐标为1的四维齐次坐标点。点到平面的距离为。
直线与平面相交
直线与平面的交点处的值为
平面相交
令为三个任意平面,令:
其中
如果是奇异矩阵,即,则三个平面不交于一点。
设令相交,交于一条直线,则可表示。
交线的表达式为
其中
视锥
视锥中,与水平视场角。对应的焦距的表达式为
焦距越短,则视场越大,视场角逐渐缩小,相机则进行放大成像,而焦距越大。
垂直视场角的表达式为
对于高宽比为的显示器,从与相机距离为的近锥平面中裁剪出的矩形的边分别为和。
透视校正插值
在透视投影中,利用相似三角形,对深度和的倒数可进行线性插值:
带透视校正的顶点属性插值可由以下类似的公式获得:
其中,和为顶点属性值,表明三角形面上的插值属性与坐标值的倒数的乘积是线性插值。
投影
为了将一个三维场景渲染在一个二维显示器屏幕上,场景中的每个顶点在屏幕上显示位置。如前所述,对于位于点的一个顶点,通过计算从原点发出的照向点的一束光线与投影平面交点,可求得该顶点在投影平面的投影位置。投影点的和坐标的表达式如下:
这里需注意的是的值是负的,因为相机指向坐标轴的负向。
对坐标应用式只会得到投影深度值,然而深度信息可用于隐藏面剔除算法,因此3D图形系统使用四维空间的齐次坐标对顶点进行投影。
透视投影
透视投影可将顶点的和坐标投影到投影平面的正确位置,而同时保留深度信息。通过将视锥映射成立方体可实现透视投影,该立方体是所谓的齐次裁剪空间在3D空间的投影,在OpenGL中,它的中心与坐标系原点重合,分别沿坐标轴扩展到。
到齐次裁剪空间的映射首先用一个投影矩阵将相机空间的点的负z坐标添加到变换点的坐标,接着除以坐标则得到一个有规范化设备坐标的三维点。
令是相机空间中的一个齐次坐标点,该点位于视锥内部。在OpenGL中,函数gIFrustum();
的参数包括一个矩形的四条边,函数申城透视投影矩阵。
将相机空间的点变换到裁剪空间的透视投影矩阵为
其中,和分别是从相机到近锥平面和远锥平面的距离,分别是从近锥平面裁剪出来的观察矩形的左、右、底和顶边。
通过使远锥平面的距离趋于无穷大,可以构造一个无限视锥,符合规范化设备坐标系(NDC),相应的投影矩阵为
正投影
相机空间的点总是被与相机观察方向平行的光线映射到投影平面。
正投影的可见区由一个位于平面的矩形、近平面和远平面距离组成。由于不存在透视扭曲,正投影中的三角形的深度可用线性插值获得,因此,向规范化设备坐标系的映射可分别在三个坐标轴上线性执行。
将和坐标分别从区间映射到区间的函数为
将三个映射函数写成矩阵的形式,可得
矩阵是OpenGL中由glOrtho();
函数产生的正投影矩阵。注意,变换后坐标为1,不会发生透视投影。
镜像与倾斜裁剪
在很多场景中,包含像镜面或者水体一类的反射表面,需要渲染这些表面中的反射图像。
显示场景中的反射图像的典型方法是建立一个专门的图像缓存区,即所谓的反射缓存,来保存场最中在反射面中可见对象的道染结果,而主场景仍然保存到主图像缓存区。当渲染反射表面的几何对象时,从反射缓存区读出相应对象的颜色混合到最终图像中。
反射场景通过一个虚拟相机渲染,该虚拟相机是主相机关于反射平面的镜像。
由于虚拟相机是原相机的反射,则虚拟相机坐标系由反射前的右手坐标系变成左手坐标系,为了适应这个变化必须采用一些专门的操作。在OpenGL中,通过调用函数glFrontFace();
可容易地翻转前向三角形的坐标顺序使其适合裁剪。
在处理虚拟相机渲染时,一些几何体与相机之间的距离比反射平面到相机的距离近。当一个物体位于反射平面两侧时会发生这种情况,这时位于反射平面背面的部分在反射过程中将被翻转,如果该几何体在反射过程中被渲染,则会在最终的渲染图像中产生一些不需要的结果。
这类问题的一个最简单解决办法是定义一个用户裁剪平面将位于反射表面的几何体裁剪掉,而不幸的是,尽管大多数GPU支持普通的用户自定义裁剪平面,而在使用时需要修改顶点或者段程序,这将带来一些麻烦,因为在渲染某一个几何体时要保存两个不同版本的顶点或者段程序,而且在不同的GPU之间实现方法也会有稍微的差异。
倾斜近锥平面裁剪
将透视投影矩阵变换为以下矩阵,可将近锥平面变换为相机空间的裁剪平面,其中
其中,,。