返回首页 现代 OpenGL 教程(连载)

modern opengl tutorial

第三十七课 延迟渲染(三)(未完待续)

第三十八课 使用Assimp导入骨骼动画(未完待续)

第三十九课 轮廓检测(未完待续)

第四十课 阴影锥(未完待续)

第四十一课 运动模糊(未完待续)

第四十二课 基于PCF的阴影(未完待续)

第四十三课 基于点光源的阴影(未完待续)

第四十四课 GLFW(未完待续)

第四十五课 屏幕空间的环境遮挡(未完待续)

第四十六课 SSAO与深度重构(未完待续)

end

第三十一课 基于PN算法的曲面细分

背景

在前面一节中我们简单介绍了 OpenGL 4.x中的曲面细分技术,我们通过对渲染管线的相关阶段进行设置,学习了如何对我们的网格模型进行细分,以及如何将由细分着色器生成的顶点渲染出来,这一节中的内容很大一部分都会依赖于上一节,所以请确保对上一节中的内容比较熟悉。细分着色器的使用是比较简单的,TES 中主要结合原始顶点信息和由 PG 阶段生成的质心坐标系下的数据对顶点进行插值,但是插值得到的点都是位于之前的平面之上的,所以我们还需要通过使用高度图使得表面产生真实的凹凸感。

在这一节中,我们将学习一种更加先进的细分技术——PN(Point-Normal)三角形,他的原理是通过一个几何上的贝塞尔表面来替换原始的网格数据进而对精细度较低的网格进行平滑处理。

贝塞尔曲面是 Pierre Bezier 在 1960 年代发明的,他的初衷是用这个技术来描述汽车车身的曲面部分。简而言之,贝塞尔曲面就是一个描述光滑的连续的曲面的多项式函数,并且这个曲面全部包含在一组控制点内。贝塞尔曲面有一个特殊的性质,当我们移动一个控制点时,这个控制点附近的表面都会受到影响,而且离这个点越远,这个影响变得越小。你可以想象有一个十分纤细而且有弹性的布料平铺在地面上,当你用手拿住布料的某一个点向上提时,你可以发现在这个点附近会形成一个曲面,而且离这个点越远,这个曲面会变得更加不明显。

贝塞尔曲面多项式是定义在一个单位正方形之上的,这意味着我们可以通过向多项式中插入一组在[0 - 1] 之间的数据,就能得到多项式所描述的光滑曲面上的一个点。如果你在这个单位正方形中插入很多组数据,并将结果绘制到屏幕上,最终你会得到一个近似的曲面。

我们将会使用贝塞尔曲面中的一个特例——Bezier Triangle,它的形式如下:

让我们一步一步的来理解上面这个公式,‘u/v/w’ 是质心坐标(他们始终满足等式:u + v + w = 1),‘Bxyz’ 是一组控制点,我们会对标准的贝塞尔三角形进行一些改动,并如下放置控制点。

正如你所见的那样,一组控制点大体就是三角形表面上的一个膨胀表面,将质心坐标带入上面的这个公式,我们就能得到更加接近真实的 3D 表面。

让我们看看如何将这些数学知识整合进细分管线中,我们先从一个三角形开始,这会是我们作为我们的输入 patch(就和前一课中一样)。我们会生成 10 个控制点并在 TCS 着色器中决定细分层级(TLS)。PG 阶段会根据 TLs 对三角形域进行划分,进而生成新的顶点,对于每个新生成的顶点都会对其执行 TES 着色器。在 TES 中会通过访问 PG 中得到的质心坐标,并结合从 TCS 中输出的 10 个控制点的数据,最后能得到膨胀表面的顶点。之后的处理就和之前差不多了。

还需要指出的一点就是如何生成一组控制点,PN 三角形算法建议我们这么做:

  • 初始的三角形的顶点保持不变(将其命名为 B003, B030 和 B300)。
  • 将每