15.1 图形管道概述

图形管道中数据流的概况:
应用阶段
- 建立场景:渲染之前需要先设定对整个场景有效的一些选项。比如,建立摄像机位置——视点,渲染的输出——视图。还需要设定光照与雾化,同时准备 z-缓冲
- 可见性检测
- 设置物体级的渲染状态:在渲染物体的任何片元之前,首先要设置上述选项,最常见的是纹理映射
- 几何体的生成与提交:实际向 API 提交几何体——种种形式的三角形,或是独立的三角形。此阶段,我们可能会应用 LOD,或者渐进式生成几何体
几何阶段
- 变换与光照:将顶点坐标从模型空间转换到摄像机空间,并进行顶点光照计算
- 背面剔除与裁剪:将背对摄像机的三角形去掉(背面剔除),三角形在视锥外的部分也去掉(裁剪)
- 投影到屏幕空间:在 3D 裁剪空间中经裁剪产生的多边形,被投影到输出窗口的 2D 屏幕空间里
光栅化阶段
- 光栅化:是指计算应绘制三角形上的哪些像素的过程,并为接下来的像素着色阶段提供合理的插值参数
- 像素着色:最后,计算三角形的色彩,此过程称作“着色”
15.2 设定视图参数
15.2.1 指定输出窗口
我们不一定要把图像渲染到整个屏幕,比如在分屏的多人游戏中。输出窗口即指输出设备中图像将要渲染到的那部分
要知道我们不一定在屏幕上渲染,也许只是将渲染结果保存到一个 TGA 文件里,或是 AVI 的一帧,因此,名词“帧缓冲”一般指用来保存我们正渲染图像的那块内存

15.2.2 像素横纵比
不管是渲染到屏幕还是缓冲区,我们必须知道像素的横纵比

- pixPhys 指像素物理尺寸
- devPhys 是显示设备的物理尺寸。如 23 寸
- devRes 是显示设备的像素尺寸。如 1920*1080
15.2.3 视锥
视锥是摄像机可见的空间体积,它由 6 个裁剪面围成。4 个侧面(上、左、下、右)对应着输出窗口的四边。过近或过远的物体应不可见,所以设置了近剪面和远剪面

15.2.4 视场与缩放
摄像机相比其他物体,除了都有“缩放”外,还具有“视场”这一额外属性
视场是视锥所截的角。缩放表示物体实际大小和物体在 90 度视场中显示大小的比
15.3 坐标空间
15.3.1 模型与世界空间
物体最开始由物体空间(又称模型空间或局部空间)来描述。可将坐标从模型空间转换到世界空间中,此过程称为模型转换
15.3.2 摄像机空间
通过变换,顶点从世界空间变换到摄像机空间,此空间也称作眼睛空间
15.3.3 裁剪空间
从摄像机空间,顶点接着又被变换到裁剪空间,又名标准视体空间。该变换对应的矩阵称为裁剪矩阵
裁剪矩阵将有用信息放入顶点向量的 w 分量中。它主要做两件事
- 为透视投影准备向量,由除以 w 来实现
- 规格化 x,y,z,使它们可与 w 比较,用于裁剪
裁剪矩阵的一个目的就是计算正确的 w 值,以得到正确的投影。在计算机图形学中,缩放完全由视锥的形状控制,所以 d 值(投影面距原点的距离)并不重要
如果这是裁剪矩阵唯一的目的,即计算正确的 w 值,那么它可简化为

将它乘以形如 [x, y, z, 1] 的向量再进行透视除法(除以 w),得到

裁剪矩阵的另一个目的是规格化 x, y, z 分量,使得六个裁剪面有一致的简单形式。视锥内的点满足下列不等式

任何不满足这些不等式的点都要被裁剪掉
15.3.4 屏幕空间
一旦用视锥完成了几何体裁剪,即可向屏幕空间投影,从而对应于真正的屏幕像素
15.4 光照与雾化
标准光照模型是局部模型中的一种——即当处理一个物体时,不考虑其他物体的影响,也不向别的物体投下影子
15.4.1 色彩的数学
在计算机图形学中,色彩常被视为数学实体。可以认为色彩存在于一个 3D 单位立方体“色彩空间”中

色彩可以加、减、乘以标量,和向量运算一样。两个色彩也可以作“按位乘”运算,运算记为
15.4.2 光源
光源类型:
- 点光源:向四面八方发射光线的单点。光强通常由光源中心向辐射前进方向不断衰减,最终为零。代表常见物,如灯泡、电灯、火把等
- 平行光:从无限远处射来的点光源光线,无位置的概念也无衰减。典型代表物是太阳光
- 聚光类:指从特定光源向特定方向射出的光。如信号灯、车头灯等
- 环境光:指不属于任何光源而照亮整个场景的光。没有环境光,则物体的影子将完全是黑的。但现实中这类物体常被间接照亮,这就是环境光的作用
15.4.3 标准光照方程——概述
光照方程定义了标准光照模型,用于计算单个像素的色彩,它可简写为
- 是打开光照情况下计算颜色值的结果
- 是镜面反射分量
- 是散射分量
- 是环境分量
物体外观主要取决于以下四点
- 物体表面的性质,即材质属性
- 表面的方位与朝向(单位法向量)
- 照射来的各光源性质
- 观察者位置
15.4.4 镜面反射分量
标准光照方程的镜面反射分量指由光源直接经物体表面反射入眼睛的光线。镜面反射的强度取决于物体、光源和观察者
- n 为表面法向量
- v 指向观察者
- I 指向光源。对方向光源,I 为定值
- r 为“镜象”向量,即 I 对 n 镜象之结果
- 为 r 和 v 的夹角,由 r·v 给出

为材料的光泽度,也称作 Phong 指数,它控制“亮斑”的范围。另一个有关“亮度”的值为 ,即材料的反射颜色
控制光斑的大小, 控制光斑的强度。强反射面,有大的 值
下图显示了 与 如何影响物体的镜面反射
- 从最左列到最右列由黑至白变化
- 由上至下逐行递减

15.4.5 漫反射分量
漫反射反映的是散开的随机方向上的反射,这是由物体表面的粗糙引起的。漫反射不依赖于视点的位置,因为它本来就是随机的。光源与物体的相对位置反而显得更重要
假定光线射入眼睛的几率一定,则由于垂直于光线的面在单位面积受光多于一个斜射的面,因而入射眼睛的光线更多

15.4.6 环境光分量
镜面反射和漫反射都是刻画光源经物体反射后直接进入眼中的光线,但现实世界中,光线也经常经历多于一次的反射后入眼。描述这类反射,我们可用环境光,它取决于材质和全局环境光
15.4.7 光的衰减
15.4.8 光照方程——合成
下图显示了当光分量独立存在时,各分量的视觉效果

15.4.9 雾化
现实中,光线被空气中无数粒子反射与折射。如果单位体积内粒子的浓度足够,则它们是可见的,例如烟、灰尘、雾等。计算机图形学中,上述现象都是通过雾化技术加以模拟的
15.4.10 flat 着色与 Gourand 着色
逐像素计算光照和雾化来渲染成本太大,我们必须折中来减少计算量。有两个选择:逐多边形和逐顶点计算,它们分别称作 flat 着色和 Gourand 着色
- flat 着色,对整个三角形只计算一次光照值
- Gourand 着色,又称顶点着色或插值着色。在顶点级计算光照和雾,然后这些值被线性插值用于整个多边形面

15.5 缓存
渲染涉及大量的缓存。这里,缓存只是一个简单的存有像素数据的矩形内存块。最重要缓存是帧缓存和深度缓存
帧缓存存储每个像素的色彩,即渲染后的图像。帧缓存常常在显存中,显卡不断读取该内存,并将二进制数据转化为 CRT 接收的合适信号
所谓双缓存技术,是为了防止图像在未完全渲染好之前就被显示。此时,实际上使用了两个帧缓存,一个缓存放当前显示的图像,另一个缓存,离线缓存存放正在渲染的图像

另一个用于渲染的重要缓存是深度缓存——z-buffer。深度缓存不存储像素的颜色,而是像素的尝试信息,这些信息基本上都反映物体到摄像机的距离。实践中,通常保存的是裁剪空间的 z 坐标
15.6 纹理映射
纹理图是一个铺在物体表面上的位置,使用纹理映射可以在“texel”(纹理图中的一个像素)级别控制颜色
纹理图是如何把整个物体包起来的?有多种不同的方法
- 平面映射:线性地将纹理投射于三角网,将网格用纹理图“包”起来
- 球形映射、柱形映射、立方体映射
无论位图如何放置,每个顶点都要赋给一个纹理映射坐标(uv)。用这种方式,纹理被“钉在”三角网上。要渲染三角形中的某个像素,可以先插值计算基 uv 坐标,然后读取对应的纹理值
15.7 几何体的生成与提交
一旦知道哪些物体可见(或至少潜在可见),即可将其生成并提交到图形处理器。该阶段完成以下任务:
- 细节层次(LOD)选择
- 渐进式生成几何体
- 向图形 API 提交数据
15.7.1 LOD 选择与渐进式生成
较多的三角形一般意味着低帧率,我们必须在可接受的外表和帧率间做出折衷选择。LOD 在一定程度上可两全其美,基本思路是离摄像机远的物体只使用较少的多边形,此时并不降低视觉效果
如何得到三角形数较少的三角网?一种简单的方法是让美工直接制作一个。然后根据物体离摄像机的距离(或屏幕分辨率)选用合适的 LOD
问题是在它切换三角网那一刻,会发生模型细节“跳动”的问题。一种克服“跳动”的方法是引入连续 LOD。这种系统中,不同级别 LOD 包含的三角形数几乎是连续的,渐进式网格技术就是一种这样的“网格消减”技术。但需要注意生成连续 LOD 的开支可能会很显著
15.7.2 向 API 投送几何体
API 根据操作的不同接受不同的数据格式
- 位置:描述顶点的位置
- 光照和雾化:为了渲染,顶点一般都带有色彩值。若要让 API 计算光照,通常要给出顶点法向量。如使用硬件雾化,还要指定各点的雾化强度(手动指定或由 API 计算)
- 纹理映射坐标:uv 坐标
15.8 变换和光照
网格被提交到 API 之后,接下来的操作就是变换与光照。基本上,所有顶点级别的计算都可在本阶段进行,但最常见的操作有:
- 顶点的 MVP 变换(物体空间->裁剪空间)
- 使用光照设置及法向量计算光照
- 根据顶点位置计算顶点级雾浓度
- 阶段式产生纹理映射坐标
- 在骨骼动画中,用 skinning 技术计算顶点值
15.8.1 变换到裁剪空间
MVP 变换
15.8.2 顶点光照
15.9 背面剔除与裁剪
当三角形的顶点转换到裁减空间后,我们对三角形做两个重要测试
15.9.1 背面剔除
目的是去除背对摄像机的三角形,不浪费时间去绘制任何看不见的物体。理论上,有一半三角形为背向的
有两种方法可用于探测背向三角形
- 软件渲染时代的方法:裁剪和投影前,在裁剪空间(或摄像机空间)中进行。基本思想是判断眼睛是否在三角形所在平面的前面。实际上,这只需要考虑三角形与摄像机的相对位置
- 当今流行方法:利用屏幕空间中三角形顶点的顺序(顺/逆时针)来筛选要剔除的三角形

15.9.2 裁剪
将在视锥外的三角形(全部或部分)裁剪掉,在投影到屏幕空间前确保它们完全在视锥内。裁剪操作一般由硬件完成
15.10 光栅化
裁剪以后,顶点终于可以投影到输出的屏幕坐标了。对一个单独像素,概念上会进行这三步:
- 着色:像素着色指为像素计算颜色的过程,一般先光照再雾化
- 测试:拒绝不渲染的像素。裁剪测试、深度测试、alpha 测试
- 写入:通过所有测试后,则更新帧缓存和深度缓存。帧缓存这里若需要混合,就进行新旧颜色间的混合,通常是依据 alpha 值决定它们各自的贡献