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

