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

如何在ThreeJS中通过黑白蒙版实现单材质多色效果?

用Three.js实现单材质+黑白蒙版的纯色分区上色

核心思路

利用自定义着色器,基于互不重叠的黑白蒙版纹理的采样值,直接为对应区域指定纯色,完全跳过颜色混合逻辑,实现单材质下的分区纯色效果。

具体实现步骤

1. 外部工具资源准备

  • 在Blender/Maya中为模型烘焙互不重叠的黑白蒙版纹理:每个蒙版对应一个上色区域,白色标记目标区域,黑色标记非目标区域,确保各蒙版的白色区域无重叠。
  • 导出模型(优先GLTF/GLB格式)及所有烘焙好的蒙版纹理。

2. Three.js材质实现

使用ShaderMaterial自定义着色逻辑,精准控制颜色切换:

顶点着色器(基础模板)

varying vec2 vUv;

void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

片元着色器(核心颜色切换逻辑)

uniform sampler2D mask1;
uniform sampler2D mask2;
uniform vec3 color1;
uniform vec3 color2;
uniform vec3 defaultColor;

varying vec2 vUv;

void main() {
    float maskVal1 = texture2D(mask1, vUv).r;
    float maskVal2 = texture2D(mask2, vUv).r;
    
    vec3 finalColor = defaultColor;
    
    // 蒙版互不重叠,直接判断所属区域
    if (maskVal1 > 0.9) {
        finalColor = color1;
    } else if (maskVal2 > 0.9) {
        finalColor = color2;
    }
    
    gl_FragColor = vec4(finalColor, 1.0);
}

JavaScript端资源加载与材质配置

const loader = new THREE.GLTFLoader();
const textureLoader = new THREE.TextureLoader();

// 异步并行加载资源,优化加载速度
Promise.all([
    loader.loadAsync('path/to/your-model.glb'),
    textureLoader.loadAsync('path/to/mask1.png'),
    textureLoader.loadAsync('path/to/mask2.png')
]).then(([gltf, mask1Tex, mask2Tex]) => {
    // 配置蒙版纹理参数,适配黑白图特性
    [mask1Tex, mask2Tex].forEach(tex => {
        tex.minFilter = THREE.LinearFilter;
        tex.magFilter = THREE.LinearFilter;
        tex.wrapS = THREE.ClampToEdgeWrapping;
        tex.wrapT = THREE.ClampToEdgeWrapping;
    });
    
    // 创建自定义着色器材质
    const customMat = new THREE.ShaderMaterial({
        uniforms: {
            mask1: { value: mask1Tex },
            mask2: { value: mask2Tex },
            color1: { value: new THREE.Color(0xff4444) },
            color2: { value: new THREE.Color(0x4444ff) },
            defaultColor: { value: new THREE.Color(0xeeeeee) }
        },
        vertexShader: document.getElementById('vertex-shader').textContent,
        fragmentShader: document.getElementById('fragment-shader').textContent
    });
    
    // 为模型网格替换材质
    gltf.scene.traverse(child => {
        if (child.isMesh) child.material = customMat;
    });
    
    scene.add(gltf.scene);
});

3. 优化方案

  • 多蒙版场景:将多个蒙版合并到一张纹理的RGBA通道(如R通道存蒙版1、G通道存蒙版2),减少纹理加载数量,降低绘制开销。
  • UV校验:导出模型时确保UV映射与蒙版纹理完全匹配,避免出现区域错位。

为什么这是Web环境的最优解

  • 单材质大幅减少绘制调用(draw call),提升渲染性能,尤其适合复杂场景。
  • 异步资源加载可分阶段完成,避免页面阻塞,优化用户加载体验。
  • 相比多材质方案,单材质的维护成本更低,无需管理多个材质的状态与切换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:01:02