作者:心动前端工程师 山楂
山楂最近入坑计算机图形学,在心动内部做了一次分享,分享内容主要基于闫令琪的课程。下面是这次内部分享的笔记,请配此 slide 食用。
计算机图形学在游戏、电影、设计、VR & AR、可视化、模拟、GUI、字体等领域得到广泛应用,包括光栅化(rasterization)、几何(curves & meshes)、光线追踪(ray tracing)、动画模拟(animation/simulation)等内容。其中,光栅化可以说是计算机图形学中最为基础的概念。简单来说,光栅化是将三维场景映射成平面图形,再将图形分解成多边形,多边形打碎成像素,显示到屏幕上的过程。
光栅化涉及的数学知识主要是线性代数,包括向量(求和、点积、叉积)和矩阵(乘积、转置、单位矩阵)等。光栅化涉及的大量变换都可以表达为向量和矩阵的运算。
缩放、切变、翻转、旋转这些线性变换可以用矩阵乘法表示,引入齐次坐标后,平移也同样可以像线性变换一样用矩阵乘法处理。包含俯仰、偏航、滚转的三维复杂旋转,可以用罗德里格斯旋转方程描述。
缩放、旋转、平移等基本的变换操作发生在模型变换(modeling tranformation)阶段,类似拍照过程中的找景、模特就位。模型变换之后是相机变换(view tranformation)阶段,在这一阶段我们确定相机和物体的相对位置,类似拍照过程中的找角度、放相机。具体来说,我们通过相机的位置、看向的方向、往上的方向来表示相机,然后为了简化计算,将相机和物体一起移动,在保持两者相对位置不变的前提下将相机移动至坐标系原点。下一阶段是投影变换(projection tranformation),类似拍照过程中的按快门。投影主要分为正交投影和透视投影两种。正交投影相对简单,光线平行,各点的相对位置不变,将场景平移缩放至 [-1, 1]^3
的标准立方体上,再去除 Z 值压到平面上。这里,缩放至标准立方体是为了简化计算。透视投影,近大远小,类似人眼观看物体的方式。运用近平面通过挤压不会发生变化、远平面通过挤压 Z 值不会发生变化、中心点通过挤压也不会发生变化三点性质,可以实现透视投影。这三个阶段组成了视图变换。最后还有一个视口变换(viewport transformation),将之前缩放至标准大小的场景根据屏幕的长宽再进行一次变换,投射到屏幕上。
光栅化分解图形为多边形,其中运用最广泛的是三角形,因为三角形内部是平面,内外定义很清晰,内部任意一个点都可以插值渐变。三角形输出到屏幕时,会遍历屏幕上的每个像素,通过向量的叉乘判断像素点是否在三角形内。当然,实际计算时会使用包围盒简化计算,包围盒外的像素点就不用再进行向量叉乘运算了。为了应对锯齿、摩尔纹等采样瑕疵,可以先模糊再采样。虽然对每个像素进行卷积操作可以实现模糊,但计算量比较大,所以一般使用超采样,每个像素内部增加采样点再进行平均。
利用 Z 值可以处理遮挡的问题,维护一个 Z-Buffer 记录像素点的深度,如果三角形面上的像素点 Z 值小于 Z-Buffer 中的值,那就更新 Z-Buffer 中的值为当前 Z 值,同时更新该像素点的颜色为当前三角形面上的像素点的颜色。
再接下来要处理的是着色(shading)问题,因为物体的颜色会受光照影响,更复杂的是,不同的材质和光线的相互作用不同。最基础的着色模型是Blinn-Phong反射模型,它从高光、漫反射、环境光三个维度去综合考虑着色。漫反射主要考虑材质的漫反射系数、光线强度、光源远近、入射方向和材质表面的夹角大小。不同的着色频率会产生不同的显示效果,有逐平面法线(flat shading)、逐顶点法线(gouraud shading)、逐像素法线(phong shading)三种。逐平面法线以三角形面为着色单位,计算很快,但效果较差。将共享一个顶点的所有三角形面的法线向量相加求均值,可以得到顶点的法线向量,据此可以对每个顶点进行着色,然后直接插值计算三角形面内每个点的颜色,这就是 gouraud shading。如果不直接插值计算三角形内每个点的颜色,而是直接光栅化后形成像素点,再据此对每一个点着色,就是 phong shading。
计算机图形中常常提到的渲染管线通常可分为顶点处理、三角形处理、光栅化、片元处理、帧缓冲处理,其实具体来说大致就是上面提到的这些内容。顶点处理就是对所有顶点数据进行视图变换,三角形处理就是这些顶点组合成各三角形面(三角面剖分),然后是光栅化判断像素点是否在三角形内,再接下来是片元处理,对每个片元进行着色,最后则是整合所有信息输出至屏幕。其中,片元处理除了之前提到的着色外,也可以进行纹理映射,用纹理贴图代替颜色。
最后推荐两个超棒的视频教程:
- 3Blue1Brown 的 线性代数的本质,以可视化的方式来理解线性代数(总时长:2h40m)。
- 闫令琪的 现代计算机图形学入门,全程无一句废话,通俗易懂,诙谐幽默(总时长:28h+)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。