three.js 实现渐变色柱状图

1,727 阅读2分钟

一、使用着色器

  	//第一种写法
    vec3 aColor =(1.0-vUv.y)*(color1-color2)+color2;
    //第二种写法
    //vec3 aColor  = mix(color1,color2,vUv.y);
    //第三种写法
    //vec3 aColor =(1.0-vUv.y)*color1+color2*vUv.y;
    float alp =pow((1.0-vUv.y),power);
    gl_FragColor =vec4(aColor,alp);

在 Three.js 中,可以使用 ShaderMaterial 来实现科技感材质颜色渐变效果。ShaderMaterial 是 Three.js 中一种特殊的材质,可以通过自定义着色器代码来实现复杂的图形效果。

颜色渐变效果可以通过在着色器代码中使用纹理贴图来实现。纹理贴图是一张图片,其中的颜色值将会被映射到三维空间中的物体上。

具体实现方法如下:

  1. 创建一张纹理贴图,其中包含颜色渐变效果。
  2. 在着色器代码中,使用 uv 坐标从纹理贴图中读取颜色值,并将其作为物体的颜色。
  3. 将着色器代码作为 ShaderMaterial 的参数,并将其应用到需要渐变效果的物体上。

二、更改顶点颜色

使用顶点颜色来体现柱状图颜色, lerpColors()lerp()来进行颜色插值

// 1. 计算模型y坐标高度差
loader.load("../地形.glb", function (gltf) { 
    model.add(gltf.scene);
    const mesh = gltf.scene.children[0];
    const pos = mesh.geometry.attributes.position;
    const count = pos.count;

    // 1. 计算模型y坐标高度差
    const yArr = [];//顶点所有y坐标,也就是地形高度
    for (let i = 0; i < count; i++) {
        yArr.push(pos.getY(i));//获取顶点y坐标,也就是地形高度
    }
    yArr.sort();//数组元素排序,从小到大
    const miny = yArr[0];//y最小值
    const maxy = yArr[yArr.length - 1];//y最大值
    const height = maxy - miny; //山脉整体高度 
})
// 2. 计算每个顶点的颜色值
const colorsArr = [];
const c1 = new THREE.Color(0x0000ff);//山谷颜色
const c2 = new THREE.Color(0xff0000);//山顶颜色
for (let i = 0; i < count; i++) {
    //当前高度和整体高度比值
    const percent = (pos.getY(i) - miny) / height;
    const c = c1.clone().lerp(c2, percent);//颜色插值计算
    colorsArr.push(c.r, c.g, c.b); 
}
const colors = new Float32Array(colorsArr);
// 设置几何体attributes属性的颜色color属性
mesh.geometry.attributes.color = new THREE.BufferAttribute(colors, 3);
// 3. 设置材质,使用顶点颜色渲染
mesh.material = new THREE.MeshLambertMaterial({
    vertexColors:true,
});

三、更改纹理颜色

利用lut来生成渐变色纹理,如下

let lut = new Lut();
let params = {
  colorMap: 'blackbody',
};
lut.setColorMap(params.colorMap);
lut.setMin(0);
lut.setMax(1);

 const texture = new THREE.CanvasTexture(lut.createCanvas());
 let material = new THREE.MeshPhongMaterial({
      map: texture,。
    });
const mesh = new THREE.Mesh(geometry, material);