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

基于网格高度着色的Three.js实现方案咨询

当然可行!这在Three.js里是非常常见的高度可视化需求,完全可以实现类似附图的渐变着色效果。最优方案需要根据你的模型类型来选择,下面给你详细拆解:

核心思路

不管是连续网格还是离散的小立方体,核心逻辑都是提取模型的高度信息(通常是Y轴坐标),将高度值映射到颜色渐变区间,再把颜色应用到模型上。Three.js原生支持顶点颜色和实例化颜色两种方式,能高效实现这个需求。

最优实现方案

情况1:单个连续STL网格模型

如果你的STL是一个整体的连续网格(比如地形、雕塑类模型),最直接高效的方式是基于顶点高度计算顶点颜色,让Three.js自动插值实现平滑渐变:

  1. 计算高度范围:遍历模型所有顶点的Y坐标,找到最小和最大高度,用于后续归一化计算。
  2. 生成顶点颜色:将每个顶点的Y值归一到0-1区间,再映射到你想要的颜色渐变(比如从蓝色到红色),把颜色值存入几何体的color属性。
  3. 配置材质:启用材质的vertexColors: THREE.VertexColors,让模型使用顶点颜色渲染。

代码示例

import * as THREE from 'three';
import { STLLoader } from 'three/addons/loaders/STLLoader.js';

const scene = new THREE.Scene();
// 假设你已经设置了相机、渲染器等基础环境

const loader = new STLLoader();
loader.load('你的STL模型路径.stl', (geometry) => {
  // 处理顶点颜色
  applyHeightColoring(geometry);
  
  // 创建支持顶点颜色的材质
  const material = new THREE.MeshLambertMaterial({
    vertexColors: THREE.VertexColors,
    side: THREE.DoubleSide // STL模型可能需要双面渲染
  });
  
  const mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);
});

function applyHeightColoring(geometry) {
  const positions = geometry.attributes.position.array;
  let minY = Infinity;
  let maxY = -Infinity;

  // 第一步:确定高度范围
  for (let i = 0; i < positions.length; i += 3) {
    const y = positions[i + 1];
    minY = Math.min(minY, y);
    maxY = Math.max(maxY, y);
  }
  const heightRange = maxY - minY;

  const colors = [];
  const color = new THREE.Color();

  // 第二步:为每个顶点计算颜色
  for (let i = 0; i < positions.length; i += 3) {
    const y = positions[i + 1];
    // 归一化高度值到0-1
    const normalizedHeight = (y - minY) / heightRange;
    // 用HSL颜色空间实现从蓝到红的渐变(可根据需求调整)
    color.setHSL(normalizedHeight * 0.66, 1, 0.5);
    // 将颜色RGB值存入数组
    colors.push(color.r, color.g, color.b);
  }

  // 第三步:将颜色属性添加到几何体
  geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
  geometry.colorsNeedUpdate = true;
}

情况2:由大量小立方体组成的体素模型

如果你的STL是由很多独立小立方体拼接而成的体素模型,推荐使用InstancedMesh来实现,它能大幅减少Draw Call,提升性能:

  1. 准备单个立方体的基础几何体。
  2. 收集所有立方体的位置信息,计算整体高度范围。
  3. 为每个实例设置位置和颜色:遍历所有立方体,用setMatrixAt设置位置,setColorAt根据高度设置颜色。

代码示例

import * as THREE from 'three';

const scene = new THREE.Scene();
// 假设你已经从STL中提取了所有小立方体的位置数组cubePositions

// 1. 创建基础立方体几何体和材质
const cubeGeo = new THREE.BoxGeometry(1, 1, 1); // 根据你的立方体尺寸调整
const material = new THREE.MeshLambertMaterial({ vertexColors: THREE.VertexColors });

// 2. 创建实例化网格
const instancedMesh = new THREE.InstancedMesh(cubeGeo, material, cubePositions.length);

// 3. 计算高度范围
let minY = Infinity;
let maxY = -Infinity;
cubePositions.forEach(pos => {
  minY = Math.min(minY, pos.y);
  maxY = Math.max(maxY, pos.y);
});
const heightRange = maxY - minY;

const color = new THREE.Color();
const matrix = new THREE.Matrix4();

// 4. 为每个实例设置位置和颜色
cubePositions.forEach((pos, index) => {
  matrix.setPosition(pos.x, pos.y, pos.z);
  instancedMesh.setMatrixAt(index, matrix);

  // 计算颜色
  const normalizedHeight = (pos.y - minY) / heightRange;
  color.setHSL(normalizedHeight * 0.66, 1, 0.5);
  instancedMesh.setColorAt(index, color);
});

// 标记实例颜色需要更新
instancedMesh.instanceColor.needsUpdate = true;
scene.add(instancedMesh);

补充说明

  • 颜色渐变可以自定义:除了HSL,你也可以用RGB颜色数组做线性插值,比如THREE.Color.lerpColors实现从0x0000ff到0xff0000的渐变。
  • 如果需要更复杂的着色效果(比如高度阈值高亮),可以自定义顶点着色器,在GPU层面计算颜色,性能会更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:04:02