如何在THREE.js中不使用独立Mesh修改PCB单个图形材质?
基于Three.js单Mesh实现PCB图形点击变色的高性能方案
方案1:自定义属性+着色器判断(首推)
- 合并所有图形到单个
BufferGeometry,但给每个图形的顶点加一个自定义属性(比如aObjId),同一图形的所有顶点用同一个唯一ID - 编写自定义着色器:
- 顶点着色器把
aObjId传递给片元着色器 - 片元着色器中添加
uniform变量uSelectedId存储当前选中的图形ID,对比aObjId与uSelectedId,匹配则输出选中色,否则使用默认色
- 顶点着色器把
- 点击检测:用
Raycaster发射射线,拿到交点后读取对应顶点的aObjId,更新uSelectedId的数值即可 - 优势:完全保留单Mesh的高性能,仅需修改uniform值即可切换选中状态,渲染开销与合并Mesh时一致
方案2:动态纹理映射
- 预先生成一张与PCB布局对应的纹理图,每个图形对应纹理上的一块独立区域
- 合并Mesh时为每个图形的顶点分配对应UV坐标,指向纹理上的对应位置
- 选中图形时,直接修改纹理对应区域的颜色,然后设置
texture.needsUpdate = true - 注意:纹理分辨率需足够高,避免图形边缘模糊;该方案更适合颜色单一的PCB图形
方案3:InstancedMesh(适用于大量重复图形场景)
- 如果PCB中存在大量重复图形(如同款焊盘),可使用
InstancedMesh:创建一个基础图形Mesh,批量生成实例,每个实例拥有独立的ID和变换矩阵 - 通过自定义着色器,利用
instanceId或自定义实例属性区分不同实例,实现选中变色 - 优势:性能远优于数千个独立Mesh,但仅适合图形重复度高的场景
关键实现细节
- 合并Geometry时,用
BufferAttribute存储每个顶点的objId,确保同一图形的所有顶点ID一致 - 点击检测可加入空间划分(如Octree),避免每次遍历整个Mesh的顶点,大幅提升检测速度
- 着色器uniform更新属于轻量操作,不要频繁重新编译着色器或修改Geometry,避免额外性能损耗
内容的提问来源于stack exchange,提问作者Matheos
相关产品推荐
相关产品推荐

