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

Three.js:为细分迭代顶点添加颜色区分及解决额外顶点问题

解决方案

1. 解决几何体原始顶点重复问题

Three.js的部分内置几何体(如CylinderGeometry、SphereGeometry)为实现正确的法线、UV映射,会对拓扑上的同一顶点创建多个副本(每个副本对应不同的面或法线方向),这就是你看到“额外顶点”的原因。处理方式如下:

  • 使用BufferGeometryUtils.mergeVertices()合并重复顶点,该方法会移除位置、法线、UV等属性完全一致的重复顶点,得到拓扑上唯一的原始顶点集合。
  • 代码示例:
    import { BufferGeometryUtils } from 'three/addons/utils/BufferGeometryUtils.js';
    
    // 创建原始几何体后立即去重
    const originalGeo = new THREE.CylinderGeometry(1, 1, 2, 8);
    const deduplicatedGeo = BufferGeometryUtils.mergeVertices(originalGeo);
    
    注意:去重后若需保留平滑着色效果,可调用deduplicatedGeo.computeVertexNormals()重新计算法线;若不需要平滑效果,创建几何体时可设置smoothShading: false。

2. 实现细分层级顶点的颜色区分

要区分不同细分层级的顶点,需在细分流程中给每个顶点添加自定义属性记录生成层级,再通过着色器映射颜色:

步骤1:给原始顶点添加层级属性

在去重后的原始几何体中,添加customIteration属性,将原始顶点的层级设为0:

// 初始化层级数组,所有原始顶点层级为0
const iterationArray = new Float32Array(deduplicatedGeo.attributes.position.count).fill(0);
deduplicatedGeo.setAttribute('customIteration', new THREE.BufferAttribute(iterationArray, 1));

步骤2:细分时标记新顶点的层级

无论你使用自定义细分算法还是第三方工具,在生成新顶点(如边中点、面内顶点)时,将其customIteration设为当前细分层级(1到5):

  • 示例(以边中点生成为例):
    // currentLevel为当前细分层级(从1开始)
    const midPoint = new THREE.Vector3().lerpVectors(v1, v2, 0.5); // v1、v2为边的两个端点
    // 将新顶点的层级加入数组
    iterationArray.push(currentLevel);
    
    若使用THREE.SubdivisionModifier,需修改其源码逻辑,确保在生成新顶点时同步复制或添加customIteration属性。

步骤3:着色器中根据层级分配颜色

在顶点着色器中读取customIteration属性,映射为对应颜色,片元着色器直接使用该颜色:

// 顶点着色器
attribute float customIteration;
varying vec3 vColor;

void main() {
    // 按层级定义颜色
    if (customIteration == 0.0) vColor = vec3(1.0, 0.0, 0.0);   // 原始顶点:红色
    else if (customIteration == 1.0) vColor = vec3(0.0, 1.0, 0.0); // 第1级细分:绿色
    else if (customIteration == 2.0) vColor = vec3(0.0, 0.0, 1.0); // 第2级细分:蓝色
    else if (customIteration == 3.0) vColor = vec3(1.0, 1.0, 0.0); // 第3级细分:黄色
    else if (customIteration == 4.0) vColor = vec3(1.0, 0.0, 1.0); // 第4级细分:品红
    else vColor = vec3(0.0, 1.0, 1.0); // 第5级细分:青色

    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// 片元着色器
varying vec3 vColor;

void main() {
    gl_FragColor = vec4(vColor, 1.0);
}

额外提示

  • 调整mergeVertices的精度参数(默认0.0001)可控制顶点合并的严格程度,避免误合并位置接近的不同顶点。
  • 若细分后几何体的属性出现异常,需确保所有自定义属性在细分过程中都被正确复制或更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:48:12