跳过正文
  1. Posts/

GAMES101学习笔记05:光栅化(三角形的离散化)

··2079 字·5 分钟·
Xenolies
作者
Xenolies
Keep On Keeping On

声明:部分内容参考网上博客。

教程地址: # GAMES101-现代计算机图形学入门-闫令琪

课程主页: # GAMES101: 现代计算机图形学入门

作业汇总: http://games-cn.org/forums/topic/allhw/

一些笔记参考: TA学习笔记

三角形网格(Triangle Meshes)
#

三角形具有的性质:

  • 三角形是最简单的多边形(3条边、3个顶点),无法再简化
  • 任何复杂的多边形(如四边形、五边形甚至不规则多边形)都可以通过“三角剖分”(triangulation)算法分解成若干个三角形
  • 任意三个不共线的点必然确定一个平面 → 三角形一定是平的
  • 三角形没有凹角、自交等问题,其“内部”区域清晰无歧义
  • 定义三个顶点后,三角形内可以插值

光栅化(Rasterization)
#

光栅化的关键作用: 哦安短一个像素和三角形的位置关系(像素中心点与三角形的位置关系)

采样(Sampling)
#

采样的过程是把一个函数离散化的过程

for(int x = 0; x < xmax; ++x)
	output[x] = f(x);

光栅化采样:利用像素中心对屏幕空间进行采样。

光栅化采样的目的:判断像素中心是否在三角形内

引用下AI举的例子:

光栅化采样 · 生活比喻(绣花版)

💬 用奶奶熟悉的十字绣,解释电脑怎么把光滑图形画到方格屏幕上。

🌸 场景设定

  • 原始图形:一张光滑圆润的牡丹花样子(连续、无锯齿)。
  • 实际画布:一块格子布(像十字绣布),由一个个小方块组成。
  • 限制:只能在整格里下针,不能绣半格、斜线或曲线。

🔍 核心规则: 看“格子中心” 对每一个小格子,只检查它的正中心点: ✅ 如果花的轮廓盖住了中心点 → 在这个格子里绣一针。 ❌ 如果没盖住 → 不绣,留空。

这个“看中心点”的判断动作,就是 采样(Sampling)

🖼️ 结果 - 绣出来的花是由方格组成的,边缘有“小台阶”(锯齿)。

  • 站远一点看,依然是一朵完整的花!
  • ——这和电脑在屏幕上画图完全一样

🧠 对应到计算机图形学

光滑的花样子 –> 3D 几何图元(如三角形)

格子布 –> 屏幕像素网格

每个格子的中心–>像素采样点

“盖住中心就绣” –>光栅化采样规则

绣出的花–>光栅化后的图像(帧缓冲)

💡 一句话总结 光栅化采样 = 电脑“绣花”——看每个像素的“心”有没有被图形盖住,盖住了就点亮它!

$$ \text{inside}(t, x, y) = \begin{cases} 1 & \text{Point } (x, y) \text{ in triangle } t \\ 0 & \text{otherwise} \end{cases} $$
// 从屏幕最左边(x=0)开始,一直扫描到最右边(x = xmax - 1) 
for (int x = 0; x < xmax; ++x) 
// 在当前这一列(x 固定),从屏幕最上边(y=0)扫到最下边(y = ymax - 1) 
	for (int y = 0; y < ymax; ++y) 
// 判断当前像素是否属于三角形: 
// - 每个像素是一个小方块,它的中心点坐标是 (x + 0.5, y + 0.5) 
// - 调用 inside(tri, x+0.5, y+0.5) 来检查这个中心点是否在三角形 tri 内部 
// - 如果在,inside 返回 1(点亮像素);否则返回 0(不点亮) 
		image[x][y] = inside(tri, x + 0.5, y + 0.5);

判断像素是否在三角形内
#

使用 叉乘 来判断点是否在三角形内部

三角形内外判断

一、准备工作:定义向量

我们以图中的三角形 ABC 和内部点 P 为例。

首先,给三角形的每条边定义一个有向边向量,并定义从边起点到 P 点的向量:

边向量点向量(从边起点到 P)
ABAB=B−AAP=P−A
BCBC=C−BBP=P−B
CACA=A−CCP=P−C

二、核心计算:三次叉乘

对每条边,计算 “边向量” 与 “点向量” 的叉乘。

我们在 x-y 平面进行计算,叉乘结果只有 z 分量,我们只需关注其正负号。

  1. 第一条边 AB

    c1​=AB×AP

    图中 P 在 AB 的左侧,所以 c1​>0

  2. 第二条边 BC

    c2​=BC×BP

    图中 P 在 BC 的左侧,所以 c2​>0

  3. 第三条边 CA

    c3​=CA×CP

    图中 P 在 CA 的左侧,所以 c3​>0


三、判断内外:符号一致性

  • 内部:c1​,c2​,c3​ 全部同号(全部为正,或全部为负)

    就像图中的 P 点,三个叉乘结果都为正,说明它始终在所有边的同一侧。

  • 外部:如果有任何一个结果的符号与其他不同

    说明点 P 穿过了至少一条边。 四、一句话记忆

所有叉乘结果同号 → 内部;出现异号 → 外部

三角形ABC

AB×AP , BC×BP , CA×CP 符号(方向) 相同则点P在三角形内部,否则在外部(叉乘反映向量的左右位置关系)

特殊情况:边上的点

  • 不做处理:本课程
  • 特殊处理:OpenGL/DirectX

优化—— 使用包围盒(Bounding Box)进行优化
#

因此自然的,只需要遍历每一个点就可以得出三角形的光栅化结果了!

优化:因为显然并没有必要去测试屏幕中的每一个点,一个三角形面可能只占屏幕很小的部分,可以利用一个bouding box包围住想要测试的三角形,只对该bounding box内的点进行采样测试,如下图:

  • 黄色三角形:要渲染的图元
  • 蓝色区域:包围盒(Bounding Box)
  • 红色点:在三角形内的像素(会被点亮)
  • 黑色点:在三角形外的像素(忽略)

只检查包围盒内的像素,避免对整个屏幕进行无效判断。

优点

  • ✅ 缩小搜索范围
  • ✅ 提高渲染速度
  • ✅ 减少不必要的计算

缩写:AABB (Axis-Aligned Bounding Box)

  • Bounding Box(包围盒):就是一个矩形框,把一个图形刚好包住,不多不少。
  • Axis-Aligned(轴对齐):意思是这个框的边必须跟屏幕的上下左右对齐

特点: 边与屏幕对齐,计算超快

锯齿
#

屏幕由离散像素组成,无法精确表示连续曲线 → 导致边缘出现“楼梯状”锯齿。

在经过上述的光栅化过程后,会得到如下图片,称为锯齿或走样。
而反锯齿或反走样是图形学一大挑战。