使用 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 展示帖,没有直接贴出可运行的核心代码段。作者的相关实现逻辑可从以下位置查看:

因此本文无法“保留原帖中并不存在的代码”。如果需要,可以根据作者描述进一步推导 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/渲染术语建议统一如下:

英文术语建议中文译法说明
WebGLWebGL浏览器端 3D 渲染 API,通常保留
Three.jsThree.js保留
shaders着色器细分:vertex shader 顶点着色器、fragment shader 片元着色器
textures纹理GPU 纹理资源
procedural程序化 / 过程化常用于程序化纹理或程序化生成
render target渲染目标WebGLRenderTarget,GPU 离屏绘制目标
decals贴花 / 贴花网格用于表面叠加印记的网格或投影
mesh网格常用保留,也可译作“网格模型”
stencil模板 / 镂空板此处指喷涂模板;注意与 stencil buffer(模板缓冲)区分
dispersion分散度 / 扩散喷漆颗粒分布程度
drip / drips滴落 / 流淌油漆流动效果
raycast射线投射用于从鼠标位置拾取 3D 表面
UV mappingUV 映射将 3D 表面映射到 2D 纹理坐标
splatting泼溅绘制 / 投影绘制将漆点写入纹理或目标表面
particle system粒子系统用于表现飞溅、喷雾等效果
GPU-based techniques基于 GPU 的技术利用 GPU 并行处理大量绘制
compute shader计算着色器原帖未出现,但在大量粒子/纹理更新中常见

如果你后续需要基于该方向继续开发,建议在代码和文档中保持上述术语一致,尤其是涉及 fragment shader、render target、UV mapping、raycast、splatting 等关键实现时。