如何在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
相关产品推荐
相关产品推荐

