1
00:00:01,200 --> 00:00:03,088
今天不再只给场景加效果
Today we stop adding

2
00:00:03,088 --> 00:00:06,290
我们直接打开 Shader 的工作方式
effects and open the shader itself.

3
00:00:06,290 --> 00:00:10,060
它不是一段在 CPU 上顺序执行的循环
It is not a CPU loop; the same small program

4
00:00:10,060 --> 00:00:13,830
而是同一份小程序同时跑过成千上万个像素
runs across thousands of pixels in parallel.

5
00:00:13,830 --> 00:00:19,108
接下来用五个实验，看看这套模型怎样画出黑洞、模拟水面
Five experiments will draw a black hole, simulate water,

6
00:00:19,108 --> 00:00:22,792
并让 GPU 一次计算成千上万个方向
and compute thousands of directions on the GPU.

7
00:00:25,492 --> 00:00:26,621
先看最小的例子
Start with the smallest example:

8
00:00:26,621 --> 00:00:30,007
每个 fragment 都拿到自己的屏幕坐标
every fragment receives its own screen coordinate.

9
00:00:30,007 --> 00:00:33,995
把坐标除以分辨率，就是从零到一的 UV
Divide by the resolution to get UVs,

10
00:00:33,995 --> 00:00:38,802
再把 UV 分成网格，每个格子就是一个并行线程
then tile them into a grid where each cell is a parallel thread.

11
00:00:38,802 --> 00:00:41,569
顶点 Shader 负责把几何送进来
The vertex shader feeds geometry in;

12
00:00:41,569 --> 00:00:44,934
片元 Shader 负责决定每一个像素的颜色
the fragment shader decides the color of every pixel.

13
00:00:46,834 --> 00:00:51,325
现在把每个像素当成一条从相机出发的光线
Now treat every pixel as a ray from the camera and integrate

14
00:00:51,325 --> 00:00:53,974
积分它在黑洞附近的轨迹
its path near a black hole.

15
00:00:53,974 --> 00:00:58,671
角动量在迭代中保持不变，速度方向被引力不断弯折
Angular momentum stays conserved while gravity bends the velocity;

16
00:00:58,671 --> 00:01:00,969
落入视界的光线直接变黑
rays crossing the horizon go black.

17
00:01:00,969 --> 00:01:05,380
光线穿过赤道面时，再采样一圈发光吸积盘
When a ray crosses the equatorial plane, sample a glowing disk with temperature,

18
00:01:05,380 --> 00:01:08,434
加入温度、旋转和多普勒增强
rotation, and Doppler boost.

19
00:01:08,434 --> 00:01:10,834
这不是贴图，也没有模型
There is no texture or model:

20
00:01:10,834 --> 00:01:15,113
每个像素都独立完成一次小型的天体物理实验
every pixel runs its own tiny astrophysics experiment.

21
00:01:17,613 --> 00:01:20,671
同样的并行模型也能做水面
The same parallel model can simulate water by

22
00:01:20,671 --> 00:01:24,218
把高度和速度存进一张浮点纹理
storing height and velocity in a floating-point texture.

23
00:01:24,218 --> 00:01:27,519
每次 pass 读取上下左右四个邻居
Each pass reads four neighbors,

24
00:01:27,519 --> 00:01:32,068
用离散拉普拉斯算子更新波动，再把结果写入另一张纹理
applies a discrete Laplacian, and writes into the other texture.

25
00:01:32,068 --> 00:01:36,097
两张纹理来回交换，就是 ping-pong
Swapping two textures is ping-pong:

26
00:01:36,097 --> 00:01:40,313
这里没有 CPU 往返，波纹完全留在 GPU
the ripples stay on the GPU with no CPU round trip.

27
00:01:40,313 --> 00:01:42,751
最后用高度差重建法线
Rebuild normals from height differences,

28
00:01:42,751 --> 00:01:46,117
菲涅尔和高光就会跟着波峰移动
and Fresnel highlights move with every crest.

29
00:01:48,317 --> 00:01:51,959
把纹理里的每一个 texel 换成一个智能体
Replace each texel with an agent and you get batched

30
00:01:51,959 --> 00:01:53,497
就得到批量朝向计算
orientation updates.

31
00:01:53,497 --> 00:01:55,654
位置和朝向打包在 RGBA 里
Position and heading are packed into RGBA,

32
00:01:55,654 --> 00:01:59,482
fragment Shader 一次更新成千上万个个体
so one fragment pass updates thousands of agents.

33
00:01:59,482 --> 00:02:03,002
再用一张更小的网格做邻域投票
A smaller grid performs neighborhood voting and

34
00:02:03,002 --> 00:02:06,037
把局部方向反馈给所有个体
feeds a local direction back to every agent.

35
00:02:06,037 --> 00:02:09,030
这种思路可以用于群体、粒子、机器人编队
The same pattern fits crowds, particles,

36
00:02:09,030 --> 00:02:14,173
甚至像 Dyson Sphere Program 一样分批计算朝向
robot formations, and batch orientation like Dyson Sphere Program.

37
00:02:16,373 --> 00:02:19,875
如果把射线再延长，逐步累积密度
Extend the ray and accumulate density step by step

38
00:02:19,875 --> 00:02:22,248
就能得到体积云和星云
to create clouds and nebulae.

39
00:02:22,248 --> 00:02:26,721
每一步只做一次噪声采样、光照和透明度衰减
Each step samples noise, lighting, and transmittance;

40
00:02:26,721 --> 00:02:30,103
但几百步叠起来就是有厚度的空间
hundreds of steps build real volume.

41
00:02:30,103 --> 00:02:32,760
同一个 fragment 管线
The same fragment pipeline turns both

42
00:02:32,760 --> 00:02:36,961
从二维纹理到三维空间，都可以变成可编程的计算画布
2D textures and 3D space into programmable canvases.

43
00:02:39,261 --> 00:02:42,783
这就是 Shader 最容易被低估的地方
That is the underestimated part of shaders:

44
00:02:42,783 --> 00:02:46,476
它不只是渲染颜色，而是可并行执行的数学机器
they are parallel math machines, not just color painters.

45
00:02:46,476 --> 00:02:51,405
只要把状态写进纹理，再把纹理作为下一轮输入
Write state into textures and feed them back as input to build computation,

46
00:02:51,405 --> 00:02:54,271
就能构造计算、反馈和演化
feedback, and evolution.

47
00:02:54,271 --> 00:02:56,891
WebGL 没有传统 compute Shader
Even without traditional compute shaders,

48
00:02:56,891 --> 00:03:00,847
也仍然可以用 fragment pass 搭出 GPU simulation
WebGL can build GPU simulations through fragment passes.

49
00:03:02,947 --> 00:03:08,692
从黑洞到水波，从群体到星云，变化的只是数据和方程
From black holes to waves, crowds to nebulae, only the data and equations change.

50
00:03:08,692 --> 00:03:11,194
真正的能力来自同一个循环
The real power is one loop: read state,

51
00:03:11,194 --> 00:03:14,497
读入状态，并行计算，再把结果写回
compute in parallel, and write it back.

52
00:03:14,497 --> 00:03:19,731
当你学会这样思考，Shader 就不再只是画面特效
Once you think this way, a shader is more than an effect:

53
00:03:19,731 --> 00:03:23,733
而是一台藏在浏览器里的 GPU 计算机
it is a GPU computer inside the browser.
