高级 #graphics#rasterization#depth
三角形光栅化与深度缓冲
光栅化把三角形转换成像素——判断像素在三角形内部。Z-buffer(深度缓冲)解决"哪个像素在前"的问题——每个像素存最近物体的深度值
🎨 画一个三角形——逐个像素检查
光栅化的核心问题:给定三个顶点的屏幕坐标,判断哪些像素在三角形内部。
你拿起喷漆罐在墙上喷一个三角形——喷漆(像素)只能落在三角形覆盖的区域内。你得搞清楚哪些点在里面、哪些在外面。
判断方法:重心坐标
三角形由三个顶点 A, B, C 定义。
点 P 是否在内部?→ 用重心坐标 (α, β, γ) 判断
P = α·A + β·B + γ·C
如果 α ≥ 0, β ≥ 0, γ ≥ 0 → P 在内部
任何一个是负数 → P 在外部
# 简化的判断——用叉积检查点是否在三条边的同一侧
def point_in_triangle(P, A, B, C):
def sign(p1, p2, p3):
return (p1[0]-p3[0])*(p2[1]-p3[1]) - (p2[0]-p3[0])*(p1[1]-p3[1])
d1 = sign(P, A, B)
d2 = sign(P, B, C)
d3 = sign(P, C, A)
has_neg = (d1 < 0) or (d2 < 0) or (d3 < 0)
has_pos = (d1 > 0) or (d2 > 0) or (d3 > 0)
return not (has_neg and has_pos)
🏔️ Z-buffer——哪个像素在前面?
两个三角形重叠了——谁在前面显示?
画家算法:先画远处的物体,近处的覆盖上去——但三角形互相穿插时失败。
Z-buffer 是更好的方案:每个像素存”到目前为止最近物体的深度值”。
初始化:所有像素深度 = ∞(最远)
对每个三角形的每个像素:
1. 算这个像素处三角形的深度 z
2. 如果 z < depth_buffer[x][y](更近):
→ 更新颜色和深度
3. 否则 → 被挡住了,不画
例子(两个三角形重叠):
深度缓冲: ∞ ∞ ∞
画近处(红色):0.3 0.4 0.2 → 像素变红
画远处(蓝色):0.8 > 0.3 → 不画,红色保留
⚡ 背面剔除——不要浪费性能
立方体最多只有 3 个面面向相机——另外 3 个面被挡住了。GPU 通过检查三角形顶点的绕序判断是否面向相机:
逆时针顶点 → 正面
顺时针顶点 → 背面(剔除,不渲染)
glEnable(GL_CULL_FACE); // 开启背面剔除
📝 小结
| 概念 | 一句话 |
|---|---|
| 光栅化 | 判断像素是否在三角形内部 |
| 重心坐标 | 三角形内任意点的参数化表示 |
| Z-buffer | 每个像素存最近物体的深度 |
| 背面剔除 | 跳过背向相机的面 |
为什么先学这个? 有了像素和深度,接下来学习纹理映射与滤波——怎么给三角形”贴图”。