裁剪
将观察空间规范化之后,要把在这个空间之外的东西剔除掉。
直线的裁剪
先简化问题,看直线的裁剪。
分步
- 判断是否完全在裁剪窗口内
- 如果没有,再判断是不是完全落在裁剪窗口外
- 都不完全,计算它与一个或多个裁剪边界的交点‘
基于编码的裁剪方法
思路就是上面说的,编码形式如下:
用一个四位二进制码把区域分成九个区域。
取出端点编码。
- 按位或之后为0,说明两个编码每一位都为0,那就都在窗口内。简取(意思就是很快地取这一段,不要耗费啥时间)
- 按位与之后不为零,说明两个码至少有一位都是1,记着某一位为1代表着点在那个方向里,有两个位为1代表两个点都在同一边,那一定在窗口外,则简弃(就是不费什么功夫就能不要这段)。
- 都不符合就求交点、分段再重复上面两步。
上面这个方法处理大窗口和小窗口很有效(大部分线段都可见、大部分线段都不可见)
碰到第三种情况还有一个叫做中点裁剪法,每次都把线段等分成二段,不断重复一二步,直到所有线段都在窗口内或窗口外。
Liang-Barsky算法
把直线看作有方向。它有六个候选点:进入区域点(四个),线段起始点(两个)。通过以下方法求得两端点。
给出线段的参数方程
用参数方程就可以表示上面说的六个候选点,如下。
多边形剪裁
直线的剪裁直接运用到多边形上有什么问题呢:就是失去了多边形内的信息,只有边界信息。
Sutherland-Hodgeman算法
就是一次看一条边界,每次剪裁将视图边界代替原图像边界,作为下一次裁剪的输入。
这个算法的问题:对一些凹多边形,可能会产生多余的边:
Weiler-Atherton算法
顺时针检测多边形的每一条边。
这里的第二步,是在找到一个可见到不可见点时寻找到一个多边形上最近的点当作入点,及时地确认要输出的边界
屏幕映射
裁剪空间还要转换到屏幕空间才能正常显示。OpenGL中,屏幕空间是左手系。注意这时前截面为z=0,后截面为z=1
先看z方向的变化,注意这里是相当于俯视图,两个坐标系是不同手系的。裁剪空间z的范围是[-1,1]而屏幕空间的范围要变成[0,1]。转换公式就是
z
′
=
(
1
−
z
)
/
2
z'=(1-z)/2
z′=(1−z)/2
再看xoy平面
- 平移,将观察坐标的左下角移到屏幕空间的坐标原点
- 进行比例变换,将观察窗口变成屏幕视口大小。
- 将视口图形反向平移到原来的位置
屏幕映射这个部分在现代可编程渲染管线中是GPU自动完成的。
以下是模型在渲染管线几何阶段所经历的坐标系变换