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

ThreeJS纹理问题:如何避免纹理与模型颜色相乘且保留光照效果

解决ThreeJS中纹理与模型颜色相乘问题的方案

核心问题原因

MeshStandardMaterial默认会将纹理颜色与材质自身的color属性相乘,导致印花纹理被模型颜色“染色”。要避免这个问题,同时保留PBR光照效果,有两种实用方法:


方法一:分离材质+设置白色基底(最简单)

把瓶子主体和印花网格分开,给印花材质设置白色color——白色与任何颜色相乘都不会改变纹理本身的色彩,同时完全保留MeshStandardMaterial的光照反应。

修改后的代码

材质初始化

// 印花专用材质:白色基底避免纹理被染色
const printMaterial = new THREE.MeshStandardMaterial({
  map: null,
  transparent: true,
  color: 0xffffff // 关键设置:白色不影响纹理原色
});

// 瓶子主体材质:单独设置瓶子颜色
const bottleMaterial = new THREE.MeshStandardMaterial({
  color: 0x336699 // 示例:蓝色瓶子
});

纹理应用逻辑

function applyTexture(texture) {
  const printMesh = scene.getObjectByName('Print');
  if (!printMesh) return;
  
  printMesh.traverse(child => {
    if (child.isMesh) {
      child.material.map = texture;
      child.material.needsUpdate = true;
    }
  });
}

方法二:自定义着色器钩子(保留光照的进阶方案)

如果需要更灵活的纹理混合逻辑(比如纹理透明区域显示材质颜色),可以用onBeforeCompile钩子修改MeshStandardMaterial的默认着色器,既避免颜色相乘,又完整保留PBR光照特性。

代码示例

const printMaterial = new THREE.MeshStandardMaterial({
  map: null,
  transparent: true,
  color: 0xffffff
});

// 修改默认着色器的颜色计算逻辑
printMaterial.onBeforeCompile(shader => {
  shader.fragmentShader = shader.fragmentShader.replace(
    'vec4 diffuseColor = vec4( diffuse, opacity );',
    `vec4 diffuseColor = texture2D(map, vUv);
     // 纹理透明区域 fallback 到材质颜色
     if (diffuseColor.a < 0.1) {
       diffuseColor = vec4(diffuse, opacity);
     }`
  );
});

关键注意事项

  • 确保印花网格与瓶子主体网格是独立的,避免材质互相覆盖。
  • 上传的印花图片建议用带透明通道的PNG格式,这样印花外的区域能透出瓶子颜色。
  • 保持transparent: true,确保纹理透明部分正常显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:50:14