引言
GAMES201 高级物理引擎实战是由胡渊鸣老师教授。本节主要讲述了老师与物理引擎的故事、太极编程语言以及该系列课程内容的介绍。
Physics Engine
“A physics engine is computer software that provides an approximate simulation of certain physical systems, such as rigid body dynamics (including collision detection), soft body dynamics, and fluid dynamics, of use in the domains of computer graphics, video games and film.”
我们开门见山定义一下什么是物理引擎。在维基百科上可以看到物理引擎是一个计算机软件,它提供对物理系统近似的模拟,比如刚体物理的动力学、软体动力学以及流体动力学。主要的应用是在计算机图形、游戏和电影。
Simulate the world in your computer!
这么长的定义换成一句话说就是在电脑里模拟这个世界。
Application
除了刚才说到的这些应用,它还可以应用在工业软件中,在计算机中完成测试迭代;还有一个很重要的应用是电影的视觉特效,基本每个动画电影都有非常多的镜头用物理效果模拟出来的;虚拟现实和增强现实更不用多说,如果在 VR 里有一个真实的物理世界,那么沉浸感会增强很多,虚拟世界和现实世界的物理规律是一致的。
当然,大家最关心的物理引擎的用途还是在游戏里面,所以今天就仔细讲一讲游戏。
The Incredible machines
很小的时候就玩过很多游戏,它们构成了我童年的很大一部分,有一个我印象比较深的游戏叫做 “不可思议的机器人”。这个游戏你可以摆入各种各样神奇的道具,模拟物理效果。
Angry Birds
愤怒的小鸟也是一款很经典的游戏。你可以通过拖拽弹弓,小鸟撞到游戏里各种障碍物,里面的猪碰到障碍物就会被消灭掉。
Phun (Algodoo)
另外一个更可定制一点的是纯物理引擎,不是游戏。它可以在里面放齿轮、滑轮、棱镜等等,你可以在里面创建一个物理世界。
Besieged
15 年的时候又有一款比较有意思的游戏:围攻。你可以自己把各种个样的模块把它组装成一个攻城武器,去攻打各种各样的城池。
My Own Physical Simulation Story
下面我讲讲自己和物理引擎的故事,从初中二年级到博士三年级(2009~2020)。
My first physics engine
上图是 09 写的第一个物理引擎,其实非常简单,就是一个弹簧质点系统。
My own rigid body simulator
这是高中时候做的,那时学了一点刚体动力学,受到愤怒的小鸟的影响写了一个刚体物理引擎。
My rigid body game
这是大二写的基于物理引擎的游戏。
My fluid simulator
大概 16 年的时候写了流体的模拟。
My smoke simulator
17 年的时候写了烟的模拟。
My continuum + cutting simulator
这是我第一篇 SIGGRAPH,做的是切割的模拟,实现了固体和液体显示的耦合。
Differentiable Simulation
最近在搞可微模拟,希望求出初始状况的扰动对结果的影响。
Now
Keywords of this course
Discretization
我们会简单讲讲各种各样的离散化,不会讲的特别深。因为自己是计算机方面的,所以更多会从程序员的角度讲讲怎样直观的理解各种各样的离散化。
Efficient Solvers
我们会讲怎样写有效率的求解器,后面我们会详细介绍。
Productivity
同样我们会讲讲怎么会提高生产力,怎么样用比较短的代码实现一个高效 metric。
Performance
当然我们也很在意性能,刚才提到很多模拟我们要等上一天的时间。
Hardware architecture
我们也会简单介绍一下硬件的体系结构,因为如果你要写高性能求解器,需要去了解硬件是什么样子的,否则很难把它全部利用起来。
Data Structures
还有一些复杂的数据结构,太极语言让这些数据结构的使用变得更加简单,后面我们会详细介绍。
Parallelization
我们也会讲讲怎么去做复杂的并行,因为现在并行硬件大行其道,CPU 和 GPU 如果算吞吐量真的是天壤之别,一般能差上一个数量级。
Differentiability
最后我们会讲讲怎么求 simulation 的导数,做很多有意思的东西。
Taichi Programming Language Introduction
Overview
What is Taichi?
什么是太极呢?太极是一个高性能领域特定语言,它嵌入在 python 里面,所以它的语法和 python 非常非常的像,如果你会 python,那么可以很快上手太极。
这门语言是专门用于计算机图形学而设计的,我们在设计的时候非常非常注重生产力和可移植性,这两个东西以前在计算机图形学里面是非常难以做到的。这里的生产力不是说游戏引擎,而是针对想研究图形学算法的人。
Getting started
Installation
我们先来看看如何安装。如果你有 Python 3.6 + 可以直接用以下命令安装太极:
python3 -m pip install taichi |
三个主流的操作系统都是支持的,太极程序既可以在 CPU 上运行又可以在 GPU 上运行(支持 CUDA、OpenGL、Apple Metal)。如果你的 CPU 是一些神奇的配置或 Python 是 3.9 以上,那么需要下载太极源代码下来装了。
不同操作系统所支持的后端:
平台 CPU CUDA OpenGL Metal Windows 可用 可用 可用 不可用 Linux 可用 可用 可用 不可用 Mac OS X 可用 不可用 不可用 可用 (可用:该系统上有最完整的支持;不可用:由于平台限制,我们无法实现该后端)
在参数
arch=ti.gpu
下,Taichi 将首先尝试在 CUDA 上运行。如果你的设备不支持 CUDA,那么 Taichi 将会转到 Metal 或 OpenGL。如果所在平台不支持 GPU 后端(CUDA、Metal 或 OpenGL),Taichi 将默认在 CPU 运行。
这里我选择直接在 Pycharm 中安装太极:
Initialization
初始化太极非常重要,每当你运行一个太极程序的时候总是调用一下:
import taichi as ti |
其中 arch
可以选择在什么硬件上跑,建议大家使用 ti.cpu
或 ti.gpu
。
Data
Data types
太极里支持的数据类型和 C 非常像,它有 8、16、32、64 位的整型,整型里又分为带符号的和不带符号的,还有 32、64 位的浮点数类型。
目前太极不支持 bool
类型:true
、false
,所有的比较返回值都是用整型存储。当然并不是所有的后端都支持所有的类型,因为比如 OpenGL 可能不支持 64 位的整数和浮点数,文档中有一个表详细写了每个后端支持什么样的数据类型。
Tensors
接下来我们介绍数据里最重要的概念 Tensors,一般来讲可以认为张量就是高维数组。你可以认为 0 维张量就是标量,1 维的张量就是向量,2 维的张量是一个矩阵,在太极中张量和矩阵会严格区分,是两个完全不一样的概念。
import taichi as ti |
a
是一个标量的张量,这个张量有 42x63 个元素,每一个元素是一个标量b
是一个向量的张量,这个张量由 4 个 3Dvector
组成的张量C
是一个张量的矩阵,这个矩阵有 3x5 个元素,每一个元素是 2x2 的矩阵loss
的shape
为空,说明它是一个 0D 的张量,也就是一个元素的张量:标量
不难看出,shape
是这个张量的真正维度,前面的数字表述的是这个量里面的每个元素的维度。
Computation
Kernels
计算里最重要的概念是 kernel
,太极中 kernel
是用于计算的函数。
太极 kernel
中自己有一个语言,这个语言和 Python 非常非常像,唯一的区别是这个语言会被即时编译的。太极自带一个编译器把 kernel
里面的语言编译成高性能 kernel
,这样就能摆脱 Python 运行很慢的问题。
Functions
太极的 func
可以被 kernel
调用,但不可以被 Python 调用。
Scalar math
Matrices and linear algebra
物理模拟很多时候要用到线性代数,ti.Matrix
是用来做小矩阵的。如果有很大的阶数需要考虑要不要用 tensors
而不是数组,因为太极中的一些机制会导致大数组非常慢,但小数组就会非常非常快。
Parallel for-loops
接下来我们来讲一讲并行 for
循环。太极里有两种 for
循环:
- Range-for loops 和 Python 的
for
循环没有区别 - Struct-for loops 遍历稀疏张量里所有的元素
Range-for loops
要注意的是我们只会自动并行最外层的 for
循环,如果在 for
前面嵌套一个 if
就不会被自动并行,被认为是一个 Serial,做过并行编程的同学应该很容易理解。
Struct-for loops
import taichi as ti |
我们定义了一个叫做 pixels
的 tensors
,每一个元素是 32 位的浮点数,shape
为 640x320。
Atomic Operations
并行中很多时候需要原子操作,在太极里面例如 x[i]+=1
自动是原子操作。
Taichi-scope v.s. Python-scope
- Taichi-scope 任何被
ti.kernel
或ti.func
修饰的函数 - Python-scope 任何不在 Taichi-scope 的代码
Playing with tensors in Taichi-scope
import taichi as ti |
Phases of a Taichi program
Putting everything together
import taichi as ti |
Debugging
Debug mode
下面是怎么调试太极陈谷。在初始化时设置 debug = True
时会做一些额外的检查,比如图中的数组越界。