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

如何在Three.js中实现正反颜色不同的双面网格(无需双网格)

实现Three.js正反颜色不同的双面网格

你完全可以不用创建两个网格来实现需求,通过修改材质的着色器逻辑,利用WebGL的内置变量gl_FrontFacing就能区分正反面并设置不同颜色,这样不会额外增加三角形数量,性能更优。

具体实现方案

下面以MeshBasicMaterial为例,通过onBeforeCompile方法修改片段着色器,实现正面饱和色、背面低饱和色的效果:

// 基础几何体(示例用立方体,可替换为你的几何体)
const geo = new THREE.BoxGeometry(1, 1, 1);

// 创建基础材质,设置正面颜色
const mat = new THREE.MeshBasicMaterial({
  color: 0xff0000, // 正面使用饱和红色
  side: THREE.DoubleSide // 开启双面渲染
});

// 修改着色器逻辑,区分正反面颜色
mat.onBeforeCompile = (shader) => {
  // 替换片段着色器的最终颜色输出代码
  shader.fragmentShader = shader.fragmentShader.replace(
    'gl_FragColor = vec4( outgoingLight, diffuseColor.a );',
    `
    // 通过内置变量判断当前渲染面是正面还是背面
    if(gl_FrontFacing) {
      // 正面使用原材质颜色
      gl_FragColor = vec4( outgoingLight, diffuseColor.a );
    } else {
      // 背面使用低饱和颜色(这里将原颜色转灰度,也可直接设置固定低饱和色)
      float gray = dot(outgoingLight.rgb, vec3(0.299, 0.587, 0.114));
      gl_FragColor = vec4(vec3(gray), diffuseColor.a);
    }
    `
  );
};

// 仅需一个网格即可实现需求
const obj = new THREE.Mesh(geo, mat);
scene.add(obj);

关键逻辑说明

  • gl_FrontFacing是WebGL内置布尔变量,渲染正面时为true,背面时为false,以此作为颜色分支判断的依据。
  • 若不想用灰度,可直接给背面设置固定低饱和色,比如把灰度计算代码替换为vec3(0.8, 0.2, 0.2)(低饱和度红色)。
  • 该方法同样适用于MeshStandardMaterial等其他材质,只需对应修改片段着色器中颜色输出的逻辑即可。

对比原方案的优势

  • 仅需单个网格,三角形数量与原几何体一致,避免了双倍面数带来的性能消耗。
  • 逻辑集中在材质层面,后续调整颜色或扩展效果时更易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:15:13