【问题标题】:Threejs points - set gradient color to pointsThreejs 点 - 将渐变颜色设置为点
【发布时间】:2021-08-04 08:36:24
【问题描述】:

我正在使用threejs 来创建和渲染点云。我想做的是根据每个点的 Z 坐标给每个点一个特定的颜色。这种颜色应该从具有最小 Z 坐标的某种颜色(例如具有最小 Z 坐标的绿色)映射到具有最大 Z 值的蓝色、黄色和红色。按照这种渐变方法为每个点赋予特定颜色的最简单方法是什么?

我的脚本很长,所以我把它简化为只有这几行代码:

function drawCloud(){
    for(i = 0; i < totalPoints * 3; i = i + 3){
        //Setting the new Z value of each point
        //Each third value is the Z value, therefore using i+2
        points.geometry.attributes.position.array[i+2] = theNewZValueForThisPoint;

        //Now setting the color of each point
        // i, i+1 AND i+2 is the R,G, B value of each point
        //here each point is set to a green color
        points.geometry.attributes.color.array[i] = 0;
        points.geometry.attributes.color.array[i+1] = 1;
        points.geometry.attributes.color.array[i+2] = 0;
    }    
}

function animate() {
    requestAnimationFrame( animate );
    drawCloud();
    render();
  }
  
  function render() {
    renderer.render( scene, camera );
  }


我已经创建了一种分割方法,其中每个点在一个范围内都有一个固定的颜色。像这样的:

function getColor() {
    if(ZValue > 0 && ZValue < 100){
        color = green;
    }
    if(ZValue > 100 && ZValue < 200){
        color = blue;
    }
}

这不是我想要的,因为会有一个区域的颜色发生了巨大的变化。我希望它有一个更渐变的方法,随着 Z 值的增加而缓慢变化。

请记住,此代码已在很大程度上进行了简化,以使其保持简单并仅显示基本思想。任何关于其他改进的建议也将不胜感激。

【问题讨论】:

    标签: javascript three.js


    【解决方案1】:

    假设您拥有点云的最小 z 值和最大 z 值,您可以使用此函数来获取每个点的颜色。您可以相应地在渐变数组中自定义渐变的颜色和断点:

    function getColor(z, zMin, zMax) {
      
      // normalize v in the range of vMin and vMax
      function normalize(v, vMin, vMax) {
        return ((v - vMin) / (vMax - vMin));
      }
    
      // clamp a value between min and max inclusive
      function clamp(value, min, max) {
        if (value >= max) return max;
        if (value <= min) return min;
        return value;
      }
    
      // calculates the linear interpolation of two numbers
      function lerp(a, b, alpha) {
        return a + (b - a) * clamp(alpha, 0, 1);
      }
      
      const zNorm = normalize(z, zMin, zMax);
    
      // gradient definition. Each element defines a breakpoint within the normalized z-range (0 - 1) and color
      // important: has to be sorted ascendingly by bp
      const gradient = [
        {bp: 0,   r: 0, g: 1, b: 0},
        {bp: 1/3, r: 0, g: 0, b: 1},
        {bp: 2/3, r: 1, g: 1, b: 0},
        {bp: 1,   r: 1, g: 0, b: 0}
      ];
    
      let red, green, blue;
    
      // find the color segment (between breakpoints), interpolate the color between breakpoints
      for(let i = 0, g = gradient.length; i < g; i++) {
        if(zNorm < gradient[i].bp || gradient[i].bp === 1) {
          red = lerp(gradient[i-1].r, gradient[i].r, normalize(zNorm, gradient[i-1].bp, gradient[i].bp));
          green = lerp(gradient[i-1].g, gradient[i].g, normalize(zNorm, gradient[i-1].bp, gradient[i].bp));
          blue = lerp(gradient[i-1].b, gradient[i].b, normalize(zNorm, gradient[i-1].bp, gradient[i].bp));
          break;
        }
      }
      
      return {r: red, g: green, b: blue};
    }
    

    【讨论】:

    • 谢谢。这是一个很好的解决方案。唯一的缺点是执行时间比较长。除此之外,它很好。谢谢你!
    • 如果您想加快速度,实际上可以完全省略钳位功能。 lerp 函数将如下所示:return a + (b - a) * alpha。标准化已经使 zNorm 保持在 0 和 1 之间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    • 2016-12-15
    • 2020-04-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-13
    相关资源
    最近更新 更多