使用 Three.js 在 3D 表面实时涂鸦绘画
英文原作者: xococode
原始链接: Real-time graffiti painting on 3D surfaces with Three.js
英文原标题: Real-time graffiti painting on 3D surfaces with Three.js
一、正文编译
大家好!
我最近一直在开发一个基于浏览器的 实时涂鸦模拟器,使用 Three.js。
下面是一段展示当前效果的短视频:
Simulador 3D de Graffiti en el Navegador🎨💨 (xktch.pro)
核心想法是:直接绘制到 3D 表面上,并让喷漆的手感尽可能接近物理真实。
目前我正在实验的内容包括:
- 可调节 分散度 的喷漆
- 漆滴与流淌效果
- 不同喷涂角度
- 直接在 3D mesh 表面作画
- 模板 / 镂空板可视化
- 实时交互
这个项目是 XKTCH.PRO 的一部分,那是我正在开发的更大的创意 3D 环境。
🎨 在线 Demo: https://xktch.pro
我特别希望得到 Three.js 社区在以下方面的反馈:
- 性能优化
- 在任意 mesh 上绘制
- 真实的喷漆与滴落模拟
- Decals vs. render targets vs. 其他方案 的取舍
- 用于处理大量漆料的 GPU-based techniques
目前项目仍在积极开发中,任何技术反馈或建议都将非常感谢!
谢谢!
社区回复编译
L_ng_Tu_n_Anh:
我觉得这里可能对你有帮助:Splash Canvas — Google Arts & Culture。创造逼真的飞溅效果有很多方法,但要达到自然效果并不容易;最佳方案取决于你选择的具体实现路径。
manthrax:
我做了一个 mesh 纹理绘制工具,也许能给你一些灵感:MonkeyPaint
二、核心代码说明
原帖为 Three.js 论坛 Showcase 展示帖,没有直接贴出可运行的核心代码段。作者的相关实现逻辑可从以下位置查看:
- 在线 Demo:https://xktch.pro
- MonkeyPaint 源码:https://github.com/manthrax/monkeypaint
因此本文无法“保留原帖中并不存在的代码”。如果需要,可以根据作者描述进一步推导 render target 喷绘、投影贴花、滴落模拟等核心实现。
三、提炼:3 个核心优化要点
结合原帖作者提出的性能、任意 mesh、真实喷漆/滴落、GPU 技术等问题,可从以下三个方向入手优化。
1. 使用 GPU 渲染目标 / 纹理累积,而非大量独立 Decal 网格
作者明确提到 Decals vs. render targets vs. other approaches。
如果每喷一个漆点都创建一个独立 decal 网格,场景对象数量会迅速膨胀,CPU 端提交成本极高。更优做法是:
- 使用
WebGLRenderTarget或纹理图集作为“画布” - 将喷漆操作累积到 GPU 纹理中
- 通过全屏 quad 或在 mesh 的 UV 空间中进行 splat 写入
- 这样大量漆点可以在单个或少量 draw call 内完成
这是处理大规模漆料时最关键的 GPU 化方向。
2. 针对任意 mesh,建立稳定且低扭曲的投影与 UV 映射
原帖指出“Painting onto arbitrary meshes”是重点。
任意 mesh 往往 UV 展开不均匀,直接依赖原生 UV 会导致明显拉伸。可以采用:
- 屏幕空间投影:把 raycast 命中点映射到屏幕空间纹理
- 切线空间 / 局部空间投影:在命中点附近按表面切线方向建立局部坐标
- 三平面投影(triplanar projection):减少复杂模型上的 UV 接缝问题
- 对特殊模型可预先烘焙 UV,或使用局部投影混合
核心目标是:让喷漆在任意网格上都能自然附着,不产生严重变形。
3. 喷溅与滴落模拟尽量在 shader 中完成
原帖提到“Realistic spray and drip simulation”以及“GPU-based techniques”。
推荐思路:
- 喷溅喷洒:在 fragment shader 中叠加噪声、径向衰减、角度扰动,模拟 adjustable dispersion 和不同 spray angles
- 滴落流淌:在 render target 上执行多次模糊 + 向下偏移 pass,模拟重力导致的 drip
- 粒子系统:用于表现短暂飞溅粒子,但长期累积漆层仍应写入纹理
- 所有参数(分散度、喷涂角度、重力大小)暴露为 uniform,保持实时可调
这样可以避免每帧更新大量网格,使性能集中在 GPU 并行计算上。
四、GLSL / WebGL 专业术语检查
原帖没有直接给出 GLSL 代码,因此不涉及具体语法审查。但帖子中出现的关键 WebGL/渲染术语建议统一如下:
| 英文术语 | 建议中文译法 | 说明 |
|---|---|---|
| WebGL | WebGL | 浏览器端 3D 渲染 API,通常保留 |
| Three.js | Three.js | 保留 |
| shaders | 着色器 | 细分:vertex shader 顶点着色器、fragment shader 片元着色器 |
| textures | 纹理 | GPU 纹理资源 |
| procedural | 程序化 / 过程化 | 常用于程序化纹理或程序化生成 |
| render target | 渲染目标 | WebGLRenderTarget,GPU 离屏绘制目标 |
| decals | 贴花 / 贴花网格 | 用于表面叠加印记的网格或投影 |
| mesh | 网格 | 常用保留,也可译作“网格模型” |
| stencil | 模板 / 镂空板 | 此处指喷涂模板;注意与 stencil buffer(模板缓冲)区分 |
| dispersion | 分散度 / 扩散 | 喷漆颗粒分布程度 |
| drip / drips | 滴落 / 流淌 | 油漆流动效果 |
| raycast | 射线投射 | 用于从鼠标位置拾取 3D 表面 |
| UV mapping | UV 映射 | 将 3D 表面映射到 2D 纹理坐标 |
| splatting | 泼溅绘制 / 投影绘制 | 将漆点写入纹理或目标表面 |
| particle system | 粒子系统 | 用于表现飞溅、喷雾等效果 |
| GPU-based techniques | 基于 GPU 的技术 | 利用 GPU 并行处理大量绘制 |
| compute shader | 计算着色器 | 原帖未出现,但在大量粒子/纹理更新中常见 |
如果你后续需要基于该方向继续开发,建议在代码和文档中保持上述术语一致,尤其是涉及 fragment shader、render target、UV mapping、raycast、splatting 等关键实现时。
