You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Three.js 相交Mesh着色时所有网格均被错误重着色问题咨询

问题根因

  • 最高概率原因:场景中所有Mesh共用了同一个THREE.Material实例。three.js中材质为引用传递,修改单个实例的属性会同步生效到所有引用该材质的Mesh上。
  • 次要原因:现有渲染逻辑没有对未命中射线检测的Mesh做颜色重置,所有曾经被射线命中过的Mesh都会保持红色,运行一段时间后也会出现全量Mesh变红的现象。

解决方案

第一步:修正材质实例复用问题

初始化每个Mesh时单独创建材质实例,不要全局复用同一个材质对象:

// 错误写法:所有Mesh共用同一个材质
const commonMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
const mesh1 = new THREE.Mesh(geometry, commonMaterial);
const mesh2 = new THREE.Mesh(geometry, commonMaterial);

// 正确写法1:每个Mesh单独创建材质
const mesh1 = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: 0xffffff }));
const mesh2 = new THREE.Mesh(geometry, new THREE.MeshBasicMaterial({ color: 0xffffff }));
// 正确写法2:需要复用材质属性时调用clone()生成新实例
const mesh2 = new THREE.Mesh(geometry, commonMaterial.clone());

第二步:修正渲染逻辑,增加颜色重置流程

每次渲染前先将所有Mesh的颜色恢复为默认值,再给命中的Mesh设置红色:

// 替换为你场景中Mesh的默认颜色
const DEFAULT_COLOR = '#ffffff';

function render() {
    // 遍历重置所有Mesh颜色
    scene.traverse((obj) => {
        if (obj.isMesh) {
            (obj as THREE.Mesh).material.color.set(DEFAULT_COLOR);
        }
    });

    raycaster.setFromCamera(mouse, camera);
    // 若Mesh放在Group等容器下,将第二个参数改为true开启递归检测
    const intersects = raycaster.intersectObjects(scene.children, true);
    if (intersects.length > 0) {
        const targetMesh = intersects[0].object as THREE.Mesh;
        targetMesh.material.color.set('#f00');
    }
    renderer.render(scene, camera);
}

额外排查点

修改后如果问题仍存在,可打印不同Mesh的材质ID确认是否仍存在引用复用:

// 两个Mesh打印出的id相同则代表共用了同一个材质实例
console.log(mesh1.material.id, mesh2.material.id);

内容的提问来源于stack exchange,提问作者Frederik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 01:21:00