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

如何在THREE.js着色器中防止顶点颜色插值?用于网格等高线绘制

如何在Three.js着色器中防止顶点颜色插值,实现三角面纯色显示

嘿,我完全懂你想要的效果——让每个三角面呈现单一纯色,而不是顶点颜色插值出来的平滑过渡对吧?下面给你几个实用的方案,结合Three.js的特性来实现:

方案1:用内置FlatShading快速实现(最简单)

如果你用的是Three.js自带的材质(比如MeshBasicMaterial、MeshLambertMaterial),直接开启flatShading就能禁用顶点颜色插值,让每个面显示统一颜色:

const material = new THREE.MeshLambertMaterial({
  vertexColors: THREE.VertexColors,
  flatShading: true // 关键:开启后面级纯色生效
});

注意:这种方式需要给每个面的三个顶点设置完全相同的颜色,开启flatShading后整个面就会锁定这个颜色。

方案2:自定义着色器实现面纯色(更灵活)

如果需要用自定义着色器,核心思路是给每个面的所有顶点传递同一个标识/颜色值,这样片元着色器拿到的值不会因为插值而变化:

步骤1:给BufferGeometry添加面颜色属性

先给几何体的每个顶点绑定所属面的颜色(同一个面的三个顶点用同一种颜色):

// 先创建基础几何体,比如立方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const bufferGeometry = new THREE.BufferGeometry().fromGeometry(geometry);

// 准备面颜色数据:每个面对应一个颜色,每个面的3个顶点重复该颜色
const faceColors = [];
for (let i = 0; i < geometry.faces.length; i++) {
  // 随机生成面颜色,你也可以自定义固定色值
  const color = new THREE.Color();
  color.setHSL(Math.random(), 0.7, 0.5);
  // 给当前面的3个顶点都赋值这个颜色
  faceColors.push(color.r, color.g, color.b);
  faceColors.push(color.r, color.g, color.b);
  faceColors.push(color.r, color.g, color.b);
}

// 将颜色数据作为自定义属性添加到几何体
bufferGeometry.setAttribute('faceColor', new THREE.Float32BufferAttribute(faceColors, 3));

步骤2:编写自定义着色器

顶点着色器直接传递面颜色,片元着色器直接使用该值(因为同一面的顶点颜色完全一致,插值后不会改变):

// 顶点着色器
varying vec3 vFaceColor;

void main() {
  vFaceColor = faceColor; // 直接传递面颜色属性
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// 片元着色器
varying vec3 vFaceColor;

void main() {
  gl_FragColor = vec4(vFaceColor, 1.0); // 直接使用面颜色,无插值
}

步骤3:创建ShaderMaterial并使用

const shaderMaterial = new THREE.ShaderMaterial({
  vertexShader: `// 粘贴上面的顶点着色器代码`,
  fragmentShader: `// 粘贴上面的片元着色器代码`,
  vertexColors: true
});

const mesh = new THREE.Mesh(bufferGeometry, shaderMaterial);
scene.add(mesh);

方案3:针对旧版Geometry的Face3颜色设置

如果你还在使用Three.js的Geometry(非BufferGeometry),可以直接给每个Face3设置颜色:

const geometry = new THREE.BoxGeometry(1, 1, 1);
for (let i = 0; i < geometry.faces.length; i++) {
  geometry.faces[i].color.setHSL(Math.random(), 0.7, 0.5);
}

const material = new THREE.MeshBasicMaterial({
  vertexColors: THREE.FaceColors,
  flatShading: true
});

这样每个面就会显示你设置的纯色,不会有顶点插值效果。


内容的提问来源于stack exchange,提问作者Three Percent Games

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:22:09