光栅化相关
发布时间:2026/10/7 20:23:41 锦皓数字建站

章节概述上节中我们得到了屏幕坐标接下来我们需要通过光栅化将所绘制的图形映射到屏幕上进行显示。光栅化的本质就是判断屏幕上哪些像素被三⻆形覆盖并为这些像素计算属性一、为什么使用三角形三角形是图形学的基础图元。原因如下1.任意多边形都能由三角形构成 2.三点确定唯一平面不容易发生扭曲变形 3.三角形内部的属性颜色、深度、纹理坐标等等可根据三角形求出重心坐标利于进行平滑插值计算二、怎么使用三角形进行覆盖检测边函数检测法判断一个像素中心是否落在三角形内部最常用的方法是边函数Edge Function检测法。对于三角形三个顶点 V0、V1、V2以及待检测的像素中心点 P定义边函数如下对于三角形的每条边V0→V1、V1→V2、V2→V0边函数 E(P) 的计算公式为E(P) (V1.x - V0.x) * (P.y - V0.y) - (V1.y - V0.y) * (P.x - V0.x)其中 V0 和 V1 是当前边的两个端点P 是待检测的像素中心点。该公式的几何意义是边函数的值等于向量V1 - V0与向量P - V0的叉积的 z 分量它反映了点 P 相对于有向边 V0→V1 的位置关系。边函数的具体判定规则如下若 E(P) 0则点 P 位于有向边 V0→V1 的左侧逆时针方向。若 E(P) 0则点 P 位于有向边 V0→V1 的右侧顺时针方向。若 E(P) 0则点 P 恰好落在有向边 V0→V1 所在的直线上。当三角形顶点按逆时针顺序排列时点 P 位于三角形内部的充要条件是对于三条边边函数的值全部大于等于 0即满足以下条件E0(P) 0 且 E1(P) 0 且 E2(P) 0其中 E0、E1、E2 分别对应三条边V0→V1、V1→V2、V2→V0的边函数。若任意一条边的边函数值为负则点 P 位于三角形外部。具体实例如图所示边函数检测法的一个重要优势是计算效率高。对于同一三角形每条边的系数V1.x - V0.x和V1.y - V0.y是固定的因此可以预先计算并缓存。当逐行扫描像素时相邻像素的边函数值可以通过增量方式快速更新无需重复计算完整的乘法运算这大大加速了光栅化过程。三、重心坐标三角形内任意一点 P 都能对三角形的三个顶点进行加权平均即P α * V0 β * V1 γ * V2其中 α、β、γ 称为点 P 相对于三角形三个顶点 V0、V1、V2 的重心坐标且满足α β γ 1当 α、β、γ 均大于等于 0 时点 P 位于三角形内部若存在负值则点 P 位于三角形外部。因此重心坐标不仅可以用于判断点与三角形的位置关系还能对三角形内部的属性颜色、深度、纹理坐标等进行平滑插值。重心坐标的计算公式如下α (面积(P, V1, V2)) / (面积(V0, V1, V2)) β (面积(P, V0, V2)) / (面积(V0, V1, V2)) γ (面积(P, V0, V1)) / (面积(V0, V1, V2))其中面积表示对应三角形的有向面积。由于 α β γ 1实际计算时只需算出其中两个分量第三个分量可通过减法得到从而减少运算量。在光栅化过程中一旦通过边函数检测确认像素中心点位于三角形内部就可以利用该点的重心坐标对三个顶点的属性进行加权插值得到该像素对应的颜色、深度或纹理坐标这正是三角形作为基础图元能够实现平滑渐变效果的关键所在。四、透视校正插值我们利用重心坐标对三角形内部的属性进行插值。然而直接使用屏幕空间的重心坐标对属性尤其是纹理坐标进行线性插值在透视投影下会产生明显的失真。这是因为屏幕空间与三维空间之间存在透视除法屏幕上的线性关系并不对应三维空间中的线性关系。为了理解问题根源我们先回顾透视投影的过程。三维空间中的点经过透视投影后其屏幕坐标满足x_screen x_view * (near / z_view) y_screen y_view * (near / z_view)其中 x_view、y_view 是观察空间中的坐标z_view 是点到相机的深度near 是近裁剪面距离。可以看到屏幕坐标与 1/z_view 成正比这意味着屏幕空间中的线性插值在三维空间中实际上是关于 1/z 的插值。假设三维空间中一条线段上均匀分布着纹理坐标经过透视投影后这些点在屏幕上的间距不再均匀——靠近相机的部分被拉伸远离相机的部分被压缩。如果直接在屏幕空间用重心坐标线性插值纹理坐标就会得到错误的纹理映射结果表现为纹理在近处被过度拉伸、在远处被压缩这就是透视失真。透视校正插值的核心思想是不要直接对属性进行线性插值而是先对属性除以深度值 z再在屏幕空间进行线性插值最后乘以该像素处的深度值 z 进行还原。具体步骤如下第一步对每个顶点计算属性与深度的比值u/z、v/z、1/z其中 u、v 是纹理坐标z 是该顶点在观察空间中的深度值。之所以要额外计算 1/z是因为插值完成后需要用它来还原真实的深度值。第二步在屏幕空间使用重心坐标对上述比值进行线性插值(u/z)_P α * (u0/z0) β * (u1/z1) γ * (u2/z2) (v/z)_P α * (v0/z0) β * (v1/z1) γ * (v2/z2) (1/z)_P α * (1/z0) β * (1/z1) γ * (1/z2)其中 α、β、γ 是像素中心点 P 在屏幕空间的重心坐标下标 0、1、2 对应三角形的三个顶点。第三步将插值结果除以 1/z 的插值还原出该像素处真实的属性值u_P (u/z)_P / (1/z)_P v_P (v/z)_P / (1/z)_P z_P 1 / (1/z)_P这样得到的 u_P、v_P 就是经过透视校正后的正确纹理坐标z_P 则是该像素处正确的深度值可用于后续的 Z-Buffer 深度测试。透视校正插值不仅适用于纹理坐标也适用于颜色、法线、光照等所有需要在三角形内部插值的属性。其本质原因是在透视投影下三维空间中的线性属性在屏幕空间表现为关于 1/z 的线性函数因此先除以 z 再插值、最后乘回 z就能得到正确的透视效果。需要说明的是如果三角形在屏幕上的面积足够小或者深度变化不大透视失真并不明显此时可以直接使用屏幕空间线性插值以节省计算量。但在大三角形、深度跨度大或纹理细节丰富的场景中透视校正插值是保证渲染质量所必需的。五、Z-Buffer和抗锯齿1Z-Buffer当同一像素被多个三角形覆盖时需要将被遮挡的像素进行剔除。计算机需要区分谁在前谁在后因此引入深度值 Z 来进行前后关系的判断。Z-Buffer深度缓冲算法的核心思想是为屏幕上的每个像素维护一个深度缓冲区其默认的深度缓冲值初始化为无穷大记录当前已绘制到该像素的最浅深度值。在光栅化过程中每处理一个三角形都会计算其覆盖像素的深度值 Z并与深度缓冲区中已有的值进行比较若当前像素的深度值 Z 小于缓冲区中已有的深度值说明该像素更靠近观察者应更新颜色并刷新深度缓冲区若当前像素的深度值 Z 大于或等于缓冲区中已有的深度值说明该像素被遮挡直接丢弃不做任何写入。通过这种方式Z-Buffer 能够以 O(1) 的额外空间复杂度每个像素一个深度值正确解决遮挡问题且与三角形的绘制顺序无关因此成为图形管线中最常用的深度测试方案。需要注意的是Z-Buffer 的精度是有限的。由于深度值通常以浮点数存储当场景中物体距离较远或深度范围较大时可能出现深度冲突Z-fighting现象即两个表面因深度值过于接近而产生闪烁。缓解方法包括使用更高精度的深度格式、调整近远裁剪面比例、或对深度值做非线性映射。2抗锯齿在光栅化过程中三角形边缘的像素往往只被部分覆盖。若仅以像素中心是否落在三角形内部作为覆盖判定边缘处会产生明显的锯齿Jaggies表现为斜边呈阶梯状。抗锯齿Anti-Aliasing的核心思路是根据像素被三角形覆盖的面积比例来混合前景与背景颜色从而平滑边缘。最简单的抗锯齿方法是超采样SupersamplingSSAA。其做法是将每个像素细分为 N×N 个子采样点对每个子采样点分别执行覆盖检测与属性插值最后对所有子采样点的颜色取平均作为该像素的最终颜色。例如 4×4 超采样时每个像素会生成 16 个颜色样本边缘像素的颜色会按覆盖比例自然过渡从而消除阶梯感。超采样的计算公式如下Color_P (1 / (N * N)) * Σ(i1..N*N) Color_i其中 N 是每个像素边上的采样点数Color_i 是第 i 个子采样点计算出的颜色。超采样效果出色但代价是计算量随采样点数平方增长对性能要求较高。为了降低开销图形硬件普遍采用多重采样抗锯齿MSAA。MSAA 的核心优化是对每个像素的多个子采样点只做覆盖检测而属性插值颜色、深度、纹理坐标等仍以像素中心为基准计算一次。这样既保留了边缘的平滑过渡又避免了为每个子采样点重复计算昂贵的着色因此效率远高于超采样。以 4×MSAA 为例每个像素维护 4 个子采样点的覆盖掩码。当三角形覆盖其中部分子采样点时该像素的颜色按覆盖比例混合Color_P (Coverage / TotalSamples) * Color_Triangle (1 - Coverage / TotalSamples) * Color_Background其中 Coverage 是被三角形覆盖的子采样点数量TotalSamples 是子采样点总数如 4。由于深度值同样按子采样点记录MSAA 还能正确处理三角形边缘处的遮挡关系避免边缘出现错误的颜色穿插。除了硬件层面的 MSAA还有基于后处理的抗锯齿方案例如快速近似抗锯齿FXAA和时域抗锯齿TAA。FXAA 在渲染完成后对整幅图像做边缘检测并对锯齿边缘进行模糊平滑计算量小但会轻微损失细节TAA 则利用历史帧的信息对当前帧进行抖动采样与混合在较低开销下获得接近超采样的质量是当前实时渲染中广泛采用的方法。综合来看抗锯齿的本质是在渲染质量与计算开销之间做权衡超采样质量最高但最慢MSAA 在硬件支持下兼顾质量与速度FXAA 与 TAA 则适合对性能敏感的场景。在实际图形管线中通常根据目标平台和画面复杂度选择合适的抗锯齿策略。抗锯齿的本质锯齿出现的本质是因为采样率不足导致高频信号进行混叠产生的上面所述的SSAA、MSAA都是基于此本质进行处理的通常我们采用低通滤波进行抗锯齿方式即将高频波过滤让低频波通过。从信号处理的角度看图像可以看作由不同频率的信号叠加而成。三角形边缘的急剧明暗变化属于高频信号而像素网格的离散采样相当于以固定频率对图像进行采样。根据奈奎斯特采样定理当采样频率低于信号最高频率的两倍时高频成分会折叠到低频区域产生混叠Aliasing在画面上表现为锯齿或摩尔纹。因此抗锯齿的本质就是在采样之前或之后抑制高频成分使其低于采样频率的奈奎斯特极限。基于这一本质抗锯齿方法可分为两大类。第一类是提高采样率即增加采样点的密度使采样频率超过信号最高频率的两倍从而从根源上避免混叠。SSAA 和 MSAA 都属于这一类SSAA 在每个像素内布置 N×N 个子采样点MSAA 则只对覆盖检测做多采样、对着色仍以像素中心计算两者都通过增加有效采样密度来逼近真实边缘。第二类是低通滤波即在采样前对图像进行滤波将高频成分预先滤除使进入采样器的信号频率降低到奈奎斯特极限以内。FXAA 属于后处理式的低通滤波它在渲染完成后对整幅图像做边缘检测并模糊平滑等效于对高频信号进行衰减TAA 则通过时域上的多次抖动采样与混合在时间维度上累积信息等效于对高频信号做时间上的低通滤波。需要澄清的是低通滤波的方向是滤除高频、保留低频而不是相反。因为高频成分正是产生锯齿的根源将其过滤后边缘的明暗过渡变得平缓采样时不再发生混叠画面自然平滑。而低频成分对应图像中大面积的渐变区域保留它们不会产生锯齿因此无需处理。六、总结光栅化将三角形映射到屏幕像素用边函数判断覆盖用重心坐标插值属性用透视校正消除失真用 Z-Buffer 解决遮挡用抗锯齿平滑边缘核心在于以三角形为图元
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。