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

Three.js 如何给点云添加不随模型旋转、固定Z轴映射的热力图纹理

实现方案与疑问解答

核心疑问回复

  • 不能直接给Points对象添加锁定纹理实现需求:默认的PointsMaterial纹理采样基于几何体局部坐标或UV,只要点云或几何体发生旋转,采样坐标会同步偏移,无法直接绑定世界坐标的Z轴映射规则。
  • 带热力图纹理的立方体混合方案可行但不推荐:该方案需要生成包围点云的立方体,通过世界坐标采样热力图后和点云做混合,会存在半透重叠、渲染精度差的问题,性能也远低于直接处理点云的方案,性价比极低。
  • 实现需求的主流方案确实只有「预计算顶点color属性」和「自定义着色器」两类,两类方案的适用场景和实现细节如下:

方案1:预计算顶点color属性(适合静态点云)

如果你的点云顶点位置不会动态变化,也不会频繁旋转,这是成本最低的实现方案,无需编写着色器:

  1. 遍历点云所有顶点,统计所有顶点Z坐标的最大值zMax和最小值zMin
  2. 对每个顶点的Z值做归一化计算:normalizedZ = (vertexZ - zMin) / (zMax - zMin)
  3. 用normalizedZ匹配预设的热力图渐变规则(比如0对应蓝色、1对应红色,中间可自定义过渡色),将生成的RGB值写入顶点的color属性
  4. 给PointsMaterial开启vertexColors: true即可生效
    注意:如果点云会发生旋转,需要在每次旋转后重新计算所有顶点的世界坐标Z值并更新color属性,点数量超过1万时会有明显的CPU性能开销。

方案2:自定义着色器(推荐,支持动态/旋转点云)

这是最贴合你需求的方案,无需每次旋转更新数据,GPU自动完成颜色映射,性能极高:
通过自定义ShaderMaterial,直接在顶点着色器中计算点的世界坐标Z值,传入片元着色器后采样热力图输出对应颜色即可。核心代码示例如下:

顶点着色器

varying float normalizedWorldZ;
uniform float uZMin; // 点云Z轴最小值,作为uniform传入
uniform float uZMax; // 点云Z轴最大值,作为uniform传入
void main() {
  // 计算顶点的世界坐标
  vec4 worldPosition = modelMatrix * vec4(position, 1.0);
  // 归一化世界坐标Z值
  normalizedWorldZ = (worldPosition.z - uZMin) / (uZMax - uZMin);
  // 计算点的裁剪坐标和大小
  gl_Position = projectionMatrix * viewMatrix * worldPosition;
  gl_PointSize = 2.0; // 可根据需求调整点的大小
}

片元着色器

varying float normalizedWorldZ;
uniform sampler2D uHeatMap; // 1D热力图渐变纹理
void main() {
  // 用归一化的Z值采样热力图
  vec4 pointColor = texture2D(uHeatMap, vec2(normalizedWorldZ, 0.5));
  gl_FragColor = pointColor;
}

该方案无论点云如何旋转,始终基于世界坐标系的Z轴计算颜色,完全满足你红色对应Z轴正方向、蓝色对应Z轴负方向的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 14:48:02