一张存在于浏览器中的真实纸张。基于 Verlet 布料模拟的物理纸张交互实验。
Crease 是一个极简的 WebGL 实验项目。页面上只有一张灰白色纸张。鼠标按下纸张时,不是拖拽整张纸,而是像真实手指按住纸面——产生局部凹陷、褶皱、拉伸和张力传播。松开后残留的折痕会缓慢回弹,如同真实纸张被揉过。
核心算法是自定义的 Verlet 布料模拟,在 src/physics/VerletCloth.ts 中实现。
| 特性 | 参数 |
|---|---|
| 网格分辨率 | 128 × 180 = 23,040 顶点 |
| 纸张尺寸 | 2.4 × 3.4(A4 比例) |
| 结构约束刚度 | 0.85 |
| 弯曲约束刚度 | 0.85 × 0.4 |
| 约束求解迭代 | 10 次/帧 |
| 摩擦系数 | 0.985 |
| 折痕记忆系数 | 0.12 |
| 折痕恢复速率 | 0.002/帧 |
- Verlet 积分 — 通过位置差隐式计算速度,无需显式速度向量
- 结构约束 — 相邻顶点之间的弹簧约束(水平 + 垂直)
- 弯曲约束 — 间隔顶点之间的约束,抵抗纸张折叠
- 力传播 — 约束求解器自动将局部作用力沿网格扩散
- 折痕持久化 — 拉伸超过阈值后约束长度永久变形,缓慢恢复
- 局部凹陷 — 点击时 5 格半径内顶点沿 Z 轴凹陷,falloff 衰减
- 拉扯跟随 — 拖动时邻域顶点按深度比例跟随鼠标位移
| 操作 | 效果 |
|---|---|
| 单击 | 纸面局部凹陷,周围产生褶皱 |
| 拖动 | 纸张像被手指捏住拉扯,出现折痕与张力传播 |
| 快速拖动 | 形成长条折痕,出现不规则 wrinkle |
| 轻拖 | 柔和形变,无明显折痕 |
| 松开 | 残留形变缓慢回弹,部分折痕保留 |
| 再次点击 | 在新的位置产生新的凹陷 |
纸张不会整体跟随鼠标移动。鼠标作用于纸面局部,形变通过约束系统自然传播。
- 程序化生成的 1024² 纤维纹理(Canvas 2D)
- 512² 法线贴图,微表面粗糙度变化
MeshPhysicalMaterial:roughness 0.75, clearcoat 0.06- 双面渲染,褶皱区域法线实时更新
- 高级摄影棚布光
- 暖白环境光 + 三方向柔光
- ACES Filmic 色调映射
- 柔和工作台投影(ContactShadows)
- 随形变动态变化
| 技术 | 用途 |
|---|---|
| Vite | 构建工具 |
| React | UI 框架 |
| TypeScript | 类型系统 |
| Three.js | WebGL 渲染 |
| React Three Fiber | React 3D 场景管理 |
| Drei | R3F 工具库 |
| TailwindCSS | 样式 |
pnpm install
pnpm dev浏览器打开 http://localhost:5173 即可交互。
pnpm buildsrc/
├── physics/
│ └── VerletCloth.ts Verlet 布料模拟引擎
├── components/
│ └── PaperScene.tsx R3F 3D 场景 + 交互绑定
├── utils/
│ └── paperTexture.ts 程序化纹理生成
├── App.tsx 根组件
├── index.css 全局样式
└── main.tsx 入口
整个网页看起来像:一个真实存在于高级摄影棚中的灰白色纸张,被用户随手拨弄,产生完全真实的物理反馈。
