图形学基础笔记III:图形管线中的多边形裁剪算法、Sutherland-Hodgman、Guard Band Clipping

本文主要是介绍图形学基础笔记III:图形管线中的多边形裁剪算法、Sutherland-Hodgman、Guard Band Clipping,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这个主要讲的是viewport 里的。

从 frustum (根据 fov 视场角 和 aspect ratio 纵横比决定 lrbt,front、near 是由摄像机距离和世界大小决定的)到 viewport 之后,能够看到的就只有投影后的 cuboid 在 viewport 里面的东西了。

问题是这个 clipping 是在 CPU 还是 GPU?实际有多个阶段,从 culling,CPU clipping 到 GPU clipping 和GPU rasterization。

本文尝试讲解这个问题,不过实际显卡和驱动变幻莫测,还需要更多参考资料。


但是有些麻烦的是因为只能处理三角形,如果裁剪了之后变成 polygon 了就要重新划分三角形了。好在三角形切一刀只会变成三角形或者四边形(quadrilateral)。

所以可以用下面的伪代码对整个 cuboid 内的 3D 三角形进行处理。

tiger book 也分析了裁剪实际放在 mvp 之前也可以,除以齐次坐标后也可以,在mvp之后也可以,但是除法之后(世界坐标)对于眼睛附近的地方是不连续的,所以这方面的运动就很难,所以一般在 MVP 后的除法之前做,而超平面也不难表示。对于 mvp 之后的平面方程则是最简单了(因为就是正立方体)。


首先是对直线的裁剪的硬件算法,即 cohen-sutherland 算法。对于多边形的裁剪是基于直线的裁剪的 sutherland-hodgman。一般讲解的是 2D 的情况,实际有 3D 的算法。

这部分算法可能是在 CPU 做的,也可能是在 GPU(看下面的 Guard band clipping 里面就明白了,对于不同的区域而言,有一些必须 CPU 就剪好,有一些可以让 GPU 剪,最后都是看你驱动怎么实现的),而且最新的硬件算法你也不知道是什么,会经过奇特的优化,其中还涉及到插值的问题。

对于一半在 viewport 里面的三角形,其实最简单的做法是 AABB 遍历的时候只访问 viewport 里面的像素就行了,感觉也没什么,关键是你不能剪掉的啊,剪掉了那 vertex 的信息就没了(OpenGL 规定是在 VS 后面进行 clipping),还要重建新的三角形和分割,那还 render 个寂寞。

对于 hardware clipping 来说,实际你还是要进行这部分的数据传输。如果不想数据传输就涉及在 CPU 端做 culling。optimization - At what phase in rendering does clipping occur? - Stack Overflow

当然,上面说的最简单的做法是 AABB 遍历的时候只访问 viewport 里面的像素就行。但是这样实际是要求显卡的实际能用的缓冲区是要大于 viewport 的。如果你的图元连缓冲区都放不下,是不是就一定要做类似 sutherland-hodgman 然后按老虎书说的要看情况拆成两个新的三角形,还要处理边界值(根据被剪掉的顶点插值好属性从而不会丢失)。

Nvidia 和 D3D 有一个叫 guard band clipping 的 culling + clipping 的层次算法,从 CPU 一路到 GPU 的,所以可能 GPU 就没有实现:

Guard Band Clipping in Direct3D (nvidia.cn)


Cohen-Sutherland

  • 平面编码:使用 tbrl 4位编码,如果是在 viewport 的 tbrl 就为 1. 每个位置最多两个 1.
  • 在交点处把线段分为两段。其中一段完全在窗口外,可弃之。然后对另一段重复上述处理。
  • 如上图,实际只需要对直线的端点(其实一直说直线说的是线段)求这个编码,根据不同的情况,然后递归/迭代进行下去:
	// Cohen–Sutherland clipping algorithm clips a line from// P0 = (x0, y0) to P1 = (x1, y1) against a rectangle with// diagonal from (xmin, ymin) to (xmax, ymax).void CohenSutherlandLineClipAndDraw(double x0,double y0,double x1,double y1) {// compute outcodes for P0, P1, and whatever point lies outside the clip// rectangleOutCode outcode0 = ComputeOutCode(x0, y0);OutCode outcode1 = ComputeOutCode(x1, y1);bool accept = false;while (true) {if (!(outcode0 | outcode1)) {// bitwise OR is 0: both points inside window; trivially accept and exit// loopaccept = true, break;} else if (outcode0 & outcode1) {// bitwise AND is not 0: both points share an outside zone (LEFT, RIGHT,// TOP, or BOTTOM), so both must be outside window; exit loop (accept is// false)break;} else {// failed both tests, so calculate the line segment to clip// from an outside point to an intersection with clip edgedouble x, y;// At least one endpoint is outside the clip rectangle; pick it.OutCode outcodeOut = outcode1 > outcode0 ? outcode1 : outcode0;// Now find the intersection point;// use formulas://   slope = (y1 - y0) / (x1 - x0)//   x = x0 + (1 / slope) * (ym - y0), where ym is ymin or ymax//   y = y0 + slope * (xm - x0), where xm is xmin or xmax// No need to worry about divide-by-zero because, in each case, the// outcode bit being tested guarantees the denominator is non-zeroif (outcodeOut & TOP)  // point is above the clip windowx = x0 + (x1 - x0) * (ymax - y0) / (y1 - y0), y = ymax;else if (outcodeOut & BOTTOM)  // point is below the clip windowx = x0 + (x1 - x0) * (ymin - y0) / (y1 - y0), y = ymin;else if (outcodeOut & RIGHT)  // point is to the right of clip windowy = y0 + (y1 - y0) * (xmax - x0) / (x1 - x0), x = xmax;else if (outcodeOut & LEFT)  // point is to the left of clip windowy = y0 + (y1 - y0) * (xmin - x0) / (x1 - x0), x = xmin;// Now we move outside point to intersection point to clip// and get ready for next pass.if (outcodeOut == outcode0)x0 = x, y0 = y, outcode0 = ComputeOutCode(x0, y0);elsex1 = x, y1 = y, outcode1 = ComputeOutCode(x1, y1);}}
}

Sutherland-Hodgman 多边形裁剪算法

  • 关键在于怎么确定凸的凹的那些要不要封闭。
  • 按某个顺序逐边裁剪:

  • 多边形边的分类:把所有边都按逆时针确定起点 S 和终点 P。每次裁剪的时候,viewport 边界裁剪线要做延长,再划分 in out 分区

  • case1 是整条边都在viewport 里面的(通过 Cohen-Sutherland 得知的),只保留终点。
  • case2 是内往外出,保留交点。(起点会由另一个闭合边输出),交点的求法可以用数值解。
  • case3 边在外面,不保留顶点。
  • case4 外面进来,保留交点和终点。
  • 一言:对于相交的, viewport 内的终点,以及交点都要保留

  • 后处理:由于这个算法输出的是点,这里演示了一个凹多边形,所以你怎么把连连起来呢?wiki 说 Note that if the subject polygon was concave at vertices outside the clipping polygon, the new polygon may have coincident (i.e., overlapping) edges – this is acceptable for rendering, but not for other applications such as computing shadows.
  • 所以说必须要做一个后处理,实际你处理不了,只能加一些专家系统的解决一部分问题。不过既然三角形是凸的,所以实际可以不管他(然而我感觉用这个只处理三角形是不是有点浪费?)别的算法也是针对 polygon 的。可能说三角形还能优化。不过注意的是,对于三角形切了之后变成四边形的情况还要割呢。
  • 交点插值:由于与切割线的交点已经不是原来三角形的顶点了,所以 clipping 的过程要求一下新的顶点的重心坐标,把插值后的属性放到新的顶点上取。
  • 切分三角形:这个过程很简单的,只要切完了之后看一下有多少个顶点,如果是 4 个就切一刀,把对应 vertex 的 attributes 都要复制一份。
  • 原理:其实上边这些操作指南一样的东西,是可以用三角形来推导出来的。规定顺时针方向和逆时针方向都行。就是依次遍历三角形的三条边,然后能够依次把要保留(裁剪)的顶点不遗漏不多选地列举出来。其实那几条规则对三角形来说实在是想当然的,可以穷举所有情况,。

 


Homogeneous Clipping

  • 算法论文:p245-blinn.pdf (fabiensanglard.net)
  • 上面这个 Sutherland-Hodgman 算法一看好像只能用在 2D 上,有一定的局限。
  • 但是我们可以考虑把裁剪线扩展为裁剪面,而交点还是交点,只不过变成了 3D 的直线(线段)与平面的交点。
  • 前面提到虎书说到,我们可以在 MVP 之后,做除法之前进行 clipping。这就是齐次坐标裁剪。复习一下为什么要在除法之前进行 clipping 呢,这是因为除法之后(世界坐标)对于眼睛附近的地方是不连续的(复习 MVP 矩阵的推导),所以一般在除法之前做。(记住除法的那个 w 其实在运算过程为了化简其他,用的就是 z 就行了,也就是因为这个 z 的除法引入了反比例函数)。
  • P 矩阵的问题就是这里,回想 games101 讲 transformation II 的矩阵的推导,由于 P 矩阵主要是我们基于 x 和 y 来推导的,z 的这个是凑出来的。所以这下问题就导致最后会出错

  • 但是实际还是大部分可以是正比关系的,只要 n + f 够给力,但是反比例函数的特性,必然有一部分会被弄反。

  • 实际疯狂 google 找到齐次裁剪的关键字之后,也发现了有大佬的漂亮公式文章,这里也附上作为参考,我暂时就不研究具体公式(不过其实和上面 Sutherland-Hodgman 算法的差不多)。计算机图形学补充2:齐次空间裁剪(Homogeneous Space Clipping) - 知乎 (zhihu.com)。需要注意齐次坐标裁剪和 Sutherland-Hodgman 的关系就行。

 


实际显卡驱动中的 culling & clipping

  • Nvidia 的算法说明:Guard Band Clipping in Direct3D (nvidia.cn)
  • 由于显卡的帧缓冲是有限的,为了能够支持更大的世界,实际显卡的帧缓冲是支持比 viewport 的帧缓冲大小大得多的的,这个叫做guard band。但是他仍然是有限的,显卡能够处理的三角形也是必须在有限的空间里的(但是三角形的个数可以轻松上亿甚至十几亿),一半 60 帧的引擎同屏渲染几亿三角形应该不在话下。
  • 所以实际 CPU 传给 GPU 进行光栅化的三角形空间位置也不能超出视口太多然后还要渲染的,这样的结果是显卡自己处理不了这种三角形,因为他无法访问这么大范围的数据。

  • 所以是两阶段裁剪算法:CPU 必须保证所有传送的三角形都在 Guard band 里面。GPU 自己再裁一遍。
  • 上图,A 可以硬件丢弃,B 可以硬件裁剪。D 传送的时候就被丢掉了(驱动做),或者 CPU 可以丢掉。C 就是一个很麻烦的三角形,关键是他还和 viewport 相交了。所以必须要进行软件裁剪(CPU 进行)。

实际对于3D 来说,一些背面三角形没有必要渲染,直接丢掉,这个叫做背向面剔除

 

这篇关于图形学基础笔记III:图形管线中的多边形裁剪算法、Sutherland-Hodgman、Guard Band Clipping的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/970556

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学