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

如何动态隐藏THREE.js Points对象中的单个点?

如何动态隐藏THREE.js Points中的单个点?

当然可以实现,针对你的场景,这里有两种实用方案:

方案一:利用顶点颜色的Alpha通道控制可见性

既然你已经在使用顶点颜色,最简单的方式是把颜色格式从RGB扩展为RGBA,通过修改单个点的Alpha值来控制透明度(设为0即隐藏)。

步骤:

  1. 转换颜色属性为RGBA格式:
    原来的color属性是每个点3个值(R、G、B),需要扩展为4个值(增加Alpha通道):

    const oldColorArray = pointsObj.geometry.attributes.color.array;
    const rgbaArray = new Float32Array(oldColorArray.length * 4 / 3);
    
    // 遍历原RGB数据,填充RGBA数组,初始Alpha设为1(完全可见)
    for (let i = 0; i < oldColorArray.length; i += 3) {
      const rgbaIndex = (i / 3) * 4;
      rgbaArray[rgbaIndex] = oldColorArray[i];
      rgbaArray[rgbaIndex + 1] = oldColorArray[i + 1];
      rgbaArray[rgbaIndex + 2] = oldColorArray[i + 2];
      rgbaArray[rgbaIndex + 3] = 1;
    }
    
    // 更新几何体的color属性,itemSize设为4
    pointsObj.geometry.setAttribute('color', new THREE.BufferAttribute(rgbaArray, 4));
    
  2. 配置材质支持顶点颜色与透明:

    pointsObj.material.vertexColors = true;
    pointsObj.material.transparent = true;
    // 若出现透明点排序问题,可尝试关闭depthWrite,但可能影响深度表现
    // pointsObj.material.depthWrite = false;
    
  3. 动态控制单个点的可见性:

    // 隐藏指定索引的点
    function hidePoint(index) {
      const colorAttr = pointsObj.geometry.attributes.color;
      // 保留原RGB值,仅修改Alpha为0
      colorAttr.setXYZW(index, colorAttr.getX(index), colorAttr.getY(index), colorAttr.getZ(index), 0);
      colorAttr.needsUpdate = true; // 通知Three.js更新GPU数据
    }
    
    // 显示指定索引的点
    function showPoint(index) {
      const colorAttr = pointsObj.geometry.attributes.color;
      colorAttr.setXYZW(index, colorAttr.getX(index), colorAttr.getY(index), colorAttr.getZ(index), 1);
      colorAttr.needsUpdate = true;
    }
    

方案二:使用自定义着色器材质(ShaderMaterial)

如果点数量极大,或者不想处理透明排序问题,自定义着色器是更高效的选择——通过新增一个visibility顶点属性,在片元着色器里直接丢弃不可见的点。

步骤:

  1. 添加visibility顶点属性:

    const pointCount = pointsObj.geometry.attributes.position.count;
    const visibilityArray = new Float32Array(pointCount);
    visibilityArray.fill(1); // 初始所有点可见
    pointsObj.geometry.setAttribute('visibility', new THREE.BufferAttribute(visibilityArray, 1));
    
  2. 创建自定义着色器材质:

    const shaderMat = new THREE.ShaderMaterial({
      vertexShader: `
        attribute float visibility;
        varying float vVisibility;
        
        void main() {
          vVisibility = visibility;
          gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
          gl_PointSize = 3.0; // 可根据需求调整点大小,或用uniform传递动态值
        }
      `,
      fragmentShader: `
        varying float vVisibility;
        // 如果需要使用顶点颜色,需添加varying vec3 vColor;并在顶点着色器传递
        
        void main() {
          // 若visibility小于0.5,直接丢弃该像素(不渲染)
          if(vVisibility < 0.5) discard;
          
          // 这里可以自定义点的颜色,比如用顶点颜色:
          // gl_FragColor = vec4(vColor, 1.0);
          gl_FragColor = vec4(1.0, 0.6, 0.2, 1.0); // 示例颜色
        }
      `,
      // 不需要开启透明,性能更优
      transparent: false
    });
    
    // 替换原PointsMaterial
    pointsObj.material = shaderMat;
    
  3. 动态切换点的可见性:

    function togglePointVisibility(index, isVisible) {
      const visAttr = pointsObj.geometry.attributes.visibility;
      visAttr.setX(index, isVisible ? 1 : 0);
      visAttr.needsUpdate = true;
    }
    

方案对比

  • 方案一:无需编写着色器,上手快;但大量点修改时可能有轻微性能损耗,且透明点存在排序问题(部分点可能被错误遮挡)。
  • 方案二:性能更高,无透明排序问题,控制更灵活;需要掌握基础的GLSL着色器知识。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:50:42