游戏技术宝典:游戏编程炫酷算法合集
发表于2016-01-27
我挑一些有趣的算法,希望尽量提及相关算法在游戏中的应用。
光栅化
Bresenham's line algorithm [1]:经典的绘画直线算法,后来还可以稍作修改用于绘画圆弧[2],都不用三角函数或除数,只需用整数加法、减法和乘法。
Perspective-Correct Texture Mapping [3]:透视正确的光栅化纹理贴图算法是1980才出现的。第一代Quake引擎引入后,才开始支持不垂直的墙、不水平的地面天花。
Polygon Rasterization with Edge Function [4]:Bresenham算法如果用来画多边形,两个多边形的共边会被重绘。后来发明了使用简单的edge function去解决这个问题,而且适合并行的硬件实现。现在的GPU都是使用这个算法。
全局光照
Precomputed Radiance Transfer (PRT) with Spherical Harmonics(SH)[5]:储存静态环境对于各个方向光源的漫反射数据,可以实现动态低频光源的全局光照效果。这种表示方式非常神奇。Halo 3也使用到这种技术[6]。
Screen-space Ambient Occlusion (SSAO)[7]:Crytek提出的首个屏幕空间环境光遮蔽算法,之后引来大量的研究及改进算法。也有用类似的概念去做近距离的反射,如SSDO[8]。
Light Propagation Volume (LPV)[9]:Crytek提出的首个动态全局光照算法,不需要预计算。但要在体积数据中计算传播,性能较慢,所以之后再优化成 Cascaded LPV [10]。
Voxel Cone Tracing [11]:也是不需要预计算的动态全局光照算法。把场景动态生成层阶式的体素数据(像mipmap那样的pre-filtering),从光源视角计算直接光照,然后逐像素追踪这组数据获取非直接光照。结果比LPV精确,也可以做到光泽反射(glossy reflection)。
阴影
Shadow Volume [12]:阴影体积是1977年发表的阴影技术,在屏幕空间光栅化阴影体积,可准确判断每个屏幕像素是否在阴影之内。可以处理平行光源和点光源的阴影。1991年[13]讲述如何用stencil buffer来实现此算法,适合在图形加速硬件(当时还没有所谓GPU)上使用。但很多人发现,如果摄像机在阴影体积内,就会出错。在1998至2000年有多人发现一种解决方法,需要把John Carmack在2000年的电邮[14]中提及这个想法,后来成为2004年《毁灭战士3(Doom 3)》引擎的重要特徵,因他把这项技术发扬光大,即使他非首个发明人,此项技术通常被称为Carmack's Reverse。
Parallel Split Shadow Map (PSSM) [15][16] / Cascaded Shadow Map(CSM)[17]:虽然Shadow Volume很吸引,但它需要大量的内存频宽,而且通常不能实现软阴影。后来大部分游戏改为使用Shadow Map(阴影贴图),这更适合GPU,并且可以通过多次采样(Percentage Closer Filtering, PCF)来实现软阴影。然而,阴影贴图也有许多问题,例如远近景物都采用同一张纹理,就会令到近景的精度不足,出现锯齿。2006年香港中文大学的博士生Fan Zhang等人发表了一种 PSSM 算法 [15],为不同距离的场景渲染多张阴影贴图,在采样的时候按距离决定使用那一张。这个方法的变种CSM,在切割上和PSSM有点差异,被广泛使用于现时大部分游戏引擎中。
Variance Shadow Map(VSM)[18]:之前谈到用PCF做软阴影,它的坏处就是要做多次采样。那么可否把阴影贴图直接模糊化来实现软阴影?答案是否定的。但是在2006年有学者发表了VSM,它是一种用统计方式来逼近软阴影的效果。
场景管理
Binary Space Partitioning(BSP)
Portal rendering
Quadtree、Octree:游戏场景管理的八叉树算法是怎样的? - Milo Yip 的回答
Potential Visibility Set(PVS)
Occlusion Culling by Software Rasterization
动画/物理
Particle System
Smoothed Particle Hydrodynamics(SPH)
Curl Noise
Dual Quaternion Skinning
碰撞测试
Hyperplane separation theorem(或称separating axis theorem/SAT):凸形状相交测试的基本原理。在怎样判断平面上一个矩形和一个圆形是否有重叠? - Milo Yip 的回答中,其实背后也是使用了SAT。
Gilbert-Johnson-Keerthi distance algorithm (GJK距离算法):计算两个凸形状的距离(可用于相交测试)
Sweep and prune:用于broad phase碰撞检测,找出物体AABB是否相交。对于时空上连续的物体运动,算法最坏O(n^2)、最好O(n)。
人工智能
Minimax
Alpha-Beta Pruning
A* path finding
Dijkstra's algorithm
Finite-state machine
Behavior Tree
*欢迎分享好的算法。
光栅化
Bresenham's line algorithm [1]:经典的绘画直线算法,后来还可以稍作修改用于绘画圆弧[2],都不用三角函数或除数,只需用整数加法、减法和乘法。
Perspective-Correct Texture Mapping [3]:透视正确的光栅化纹理贴图算法是1980才出现的。第一代Quake引擎引入后,才开始支持不垂直的墙、不水平的地面天花。
(图片来自维基百科)
Polygon Rasterization with Edge Function [4]:Bresenham算法如果用来画多边形,两个多边形的共边会被重绘。后来发明了使用简单的edge function去解决这个问题,而且适合并行的硬件实现。现在的GPU都是使用这个算法。
全局光照
Precomputed Radiance Transfer (PRT) with Spherical Harmonics(SH)[5]:储存静态环境对于各个方向光源的漫反射数据,可以实现动态低频光源的全局光照效果。这种表示方式非常神奇。Halo 3也使用到这种技术[6]。
Screen-space Ambient Occlusion (SSAO)[7]:Crytek提出的首个屏幕空间环境光遮蔽算法,之后引来大量的研究及改进算法。也有用类似的概念去做近距离的反射,如SSDO[8]。
Light Propagation Volume (LPV)[9]:Crytek提出的首个动态全局光照算法,不需要预计算。但要在体积数据中计算传播,性能较慢,所以之后再优化成 Cascaded LPV [10]。
Voxel Cone Tracing [11]:也是不需要预计算的动态全局光照算法。把场景动态生成层阶式的体素数据(像mipmap那样的pre-filtering),从光源视角计算直接光照,然后逐像素追踪这组数据获取非直接光照。结果比LPV精确,也可以做到光泽反射(glossy reflection)。
阴影
Shadow Volume [12]:阴影体积是1977年发表的阴影技术,在屏幕空间光栅化阴影体积,可准确判断每个屏幕像素是否在阴影之内。可以处理平行光源和点光源的阴影。1991年[13]讲述如何用stencil buffer来实现此算法,适合在图形加速硬件(当时还没有所谓GPU)上使用。但很多人发现,如果摄像机在阴影体积内,就会出错。在1998至2000年有多人发现一种解决方法,需要把John Carmack在2000年的电邮[14]中提及这个想法,后来成为2004年《毁灭战士3(Doom 3)》引擎的重要特徵,因他把这项技术发扬光大,即使他非首个发明人,此项技术通常被称为Carmack's Reverse。
Parallel Split Shadow Map (PSSM) [15][16] / Cascaded Shadow Map(CSM)[17]:虽然Shadow Volume很吸引,但它需要大量的内存频宽,而且通常不能实现软阴影。后来大部分游戏改为使用Shadow Map(阴影贴图),这更适合GPU,并且可以通过多次采样(Percentage Closer Filtering, PCF)来实现软阴影。然而,阴影贴图也有许多问题,例如远近景物都采用同一张纹理,就会令到近景的精度不足,出现锯齿。2006年香港中文大学的博士生Fan Zhang等人发表了一种 PSSM 算法 [15],为不同距离的场景渲染多张阴影贴图,在采样的时候按距离决定使用那一张。这个方法的变种CSM,在切割上和PSSM有点差异,被广泛使用于现时大部分游戏引擎中。
Variance Shadow Map(VSM)[18]:之前谈到用PCF做软阴影,它的坏处就是要做多次采样。那么可否把阴影贴图直接模糊化来实现软阴影?答案是否定的。但是在2006年有学者发表了VSM,它是一种用统计方式来逼近软阴影的效果。
场景管理
Binary Space Partitioning(BSP)
Portal rendering
Quadtree、Octree:游戏场景管理的八叉树算法是怎样的? - Milo Yip 的回答
Potential Visibility Set(PVS)
Occlusion Culling by Software Rasterization
动画/物理
Particle System
Smoothed Particle Hydrodynamics(SPH)
Curl Noise
Dual Quaternion Skinning
碰撞测试
Hyperplane separation theorem(或称separating axis theorem/SAT):凸形状相交测试的基本原理。在怎样判断平面上一个矩形和一个圆形是否有重叠? - Milo Yip 的回答中,其实背后也是使用了SAT。
Gilbert-Johnson-Keerthi distance algorithm (GJK距离算法):计算两个凸形状的距离(可用于相交测试)
Sweep and prune:用于broad phase碰撞检测,找出物体AABB是否相交。对于时空上连续的物体运动,算法最坏O(n^2)、最好O(n)。
人工智能
Minimax
Alpha-Beta Pruning
A* path finding
Dijkstra's algorithm
Finite-state machine
Behavior Tree
*欢迎分享好的算法。