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

Three.js中如何为模型单个面添加VideoTexture,其余面用不同材质?

问题描述

我用Blender 4.2制作了包含一台电脑和两台显示器的模型,导入Three.js场景后,遍历找到名为screen-monitor-display的网格,给它设置VideoTexture时会覆盖整个网格。之后尝试给每个面加不同材质,但错误地重复赋值node.material,导致所有面都变成了MeshNormalMaterial,视频纹理失效。

需要实现:给屏幕对象的单个面添加VideoTexture,其余面设置不同材质。

解决方案

要给网格的单个面设置不同材质,需要通过材质数组+面索引分配的方式实现,具体步骤如下:

1. 准备材质数组

先创建两个材质:一个带VideoTexture的屏幕专用材质,一个用于其余面的基础材质:

const monitorScreenOne = document.getElementById( 'monitor-1-video' );
const videoTexture = new THREE.VideoTexture( monitorScreenOne );
monitorScreenOne.load();
monitorScreenOne.setAttribute('playsinline', true);

// 材质数组:索引0对应屏幕面,索引1对应其余面
const materials = [
    new THREE.MeshBasicMaterial({ map: videoTexture }),
    new THREE.MeshNormalMaterial()
];

2. 为目标面分配材质索引

根据模型使用的几何体类型(Geometry/BufferGeometry),给目标面设置对应的材质索引,再将材质数组赋值给网格:

const loader = new GLTFLoader(loadingManager);
loader.load('resources/script/lol/test.gltf', (gltf) => {
    gltf.scene.traverse(function(node) {
        if(node.name === 'screen-monitor-display' && node.isMesh) {
            node.position.x = 10;
            
            // 处理旧版Geometry类型
            if (node.geometry.isGeometry) {
                // 假设第1个面是屏幕显示面,根据你的模型实际索引调整
                node.geometry.faces[0].materialIndex = 0;
                // 其余面统一用索引1的材质
                for(let i = 1; i < node.geometry.faces.length; i++){
                    node.geometry.faces[i].materialIndex = 1;
                }
                // 通知Three.js更新几何体分组
                node.geometry.groupsNeedUpdate = true;
            } 
            // 处理新版BufferGeometry类型(GLTF导入默认用这个)
            else if (node.geometry.isBufferGeometry) {
                // 创建材质索引数组,默认全部用索引1的材质
                const materialIndices = new Uint16Array(node.geometry.attributes.position.count / 3);
                materialIndices.fill(1);
                // 将目标面(这里取第1个面)的索引设为0
                materialIndices[0] = 0;
                // 将索引数组添加为几何体属性
                node.geometry.setAttribute('materialIndex', new THREE.BufferAttribute(materialIndices, 1));
            }
            
            // 给网格应用材质数组
            node.material = materials;
        }
    });
    scene.add(gltf.scene);
});

3. 关键注意点

  • 确认目标面索引:需要在Blender中查看屏幕面的索引,或者在Three.js中打印几何体的面数据,确保设置的是正确的面。
  • BufferGeometry兼容性:新版Three.js导入GLTF默认使用BufferGeometry,优先处理这种情况。
  • 属性更新:修改材质索引后,必须触发几何体的更新通知,否则Three.js不会识别材质变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 11:45:06