Rust + WebAssembly

Rust 编译为 WebAssembly 的交互式演示

🎨 图形渲染分形、光栅化、光线追踪与程序化生成

⚛️ 物理模拟粒子、流体、布料与元胞自动机

🧮 算法与性能数据处理、搜索、几何与性能对比

🎬 多媒体图像、视频与音频处理

🛠️ 实用工具在浏览器本地完成的实用计算

🎮 游戏与 AI可以上手玩的互动演示

每个演示都是独立编译的 .wasm,页面只下载自己用到的代码。

📖 工作原理

项目是一个 Cargo workspace:每个演示都是一个独立的 Rust crate,按类别放在 crates/<类别>/<演示>/,由 wasm-pack 各自编译成一个 .wasm 并生成 JS 胶水代码。每个页面只下载自己的那一个,大多在 15~45 KB(gzip 后 6~25 KB)。多个 crate 共用的小工具(如随机数生成器)放在 crates/common,编译时静态链接进各自的 .wasm。

🔗JS 与 WASM 如何协作

JS 负责
页面交互、事件处理,以及调用浏览器 API(Canvas、WebGL、WebGPU、摄像头、Web Audio、Web Worker)。
Rust 负责
计算密集的部分,包括分形迭代、光线追踪、像素卷积、物理模拟、大数据排序过滤、博弈与约束搜索、神经网络推理、图像编码、文本解析、指令模拟和实时音频合成。
边界开销
数字可以直接传递;数组和字符串要在 JS 与 WASM 的线性内存之间复制。所以各个演示都尽量「一次传一整块」,例如一整帧像素或一页表格数据,避免频繁的细粒度调用。

📦为什么每个演示单独一个 .wasm

下载量
最初 13 个模块打成一个包时,每个页面都要下载约 159 KB(gzip 后 61 KB),现在演示已经增加到 31 个,合在一起只会更大;分开编译后,大多数页面只需 6~25 KB(gzip)。最大的是手写数字识别(约 55 KB,嵌入了神经网络权重)和 Markdown(约 34 KB,大量字符串处理)。
编译选项互不干扰
有的演示需要特殊的构建方式:光线追踪的多线程版要用 nightly 工具链带 atomics 重新编译标准库,并要求服务器返回跨源隔离的响应头;音频合成器不用 wasm-bindgen,要在 AudioWorklet 里直接实例化。放在同一个包里,这些要求会波及所有页面;分开后只影响自己那一页,多线程版不可用时光线追踪还能退回单线程构建。
代价
每个 .wasm 都带一份 Rust 运行时(内存分配、panic 处理),所有包加起来比合并时大;但每个页面只下载自己的,而且一个页面出问题不会连累其他页面。

🧩两种 Rust 模式

无状态

曼德博集合、图像滤镜、曼德博球、WebGPU 初始数据、性能对比、音频频谱、噪声地形、二维码、数据压缩、手写识别、Markdown、JPEG、数独

纯函数,输入参数,返回结果。

有状态

数据表格、生命游戏、粒子物理、迷宫寻路、流体模拟、文件哈希、落沙游戏、五子棋、光栅化、光线追踪、SIMD 对比、合成器、CHIP-8、智能缩放、波函数坍缩、布料、三角剖分

数据保存在 WASM 内存中的全局变量 static Mutex<Option<T>> 里,JS 通过「初始化 + 修改 + 读取」一组函数来操作它,不必每次都传递全部数据。

提示每个演示页面底部都有该示例的详细原理说明。