记录一下常用的简单着色器效果
发表于:2025-03-31 | 分类: 前端
字数统计: 674 | 阅读时长: 3分钟 | 阅读量:
在进行 webgis 和 webgl 项目开发中,涉及到动态可视化效果时,着色器材质是一个常用的方案,除此之外就是使用一些第三方库在地图上层再添加一个 webgl 图层,但是这种方案太重,且不同的图层所在大面不在一面,所以叠加顺序遮盖可能不好处理。
在这里着重记录更新下常用的着色器效果
  • 首先是基本的用法
  1. 新建一个 geometry 容器
  2. 新建一个 shader 材质
    1. shader 材质包含 vertexShader 和 fragmentShader
    2. 顶点着色器( vertexShader )负责处理每个顶点的位置、变换等操作
    3. 片元着色器( fragmentShader )负责计算每个像素的颜色等最终渲染效果
  3. 根据容器和材质创建 mesh
  4. 添加 mesh 到场景中
  5. 根据需要调整 mesh 的 position 和 rotation
  6. 调用 requestAnimationFrame 来更新着色器动态效果
  • 在这里只记录一下效果代码 即顶点着色器和片元着色器代码
    在实际项目使用中可以根据计算关系调整里面的数值进行效果微调
    1. 扩散波纹( shader 材质的 uniform 里需要定义 time 和 color 供片元着色器读取 )
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      const rippleVertexShader = `
      varying vec2 vUv;
      void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }
      `;

      const rippleFragmentShader = `
      uniform float time;
      uniform vec3 color;
      varying vec2 vUv;
      void main() {
      float dist = distance(vUv, vec2(0.5));
      float ripple = pow(abs(sin(dist * 20.0 - time * 2.0)), 5.0);
      float alpha = (1.0 - dist * 2.0) * ripple;
      alpha = smoothstep(0.0, 0.5, alpha);
      gl_FragColor = vec4(color, alpha * 0.6);
      }
      `;
    2. 电子围栏 渐变动态围墙
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      const vertexShader = `
      uniform float time;
      varying vec2 vUv;
      varying vec3 vNormal;

      void main() {
      vUv = uv;
      vNormal = normal;

      // 波浪效果
      float wave = sin(uv.y * 15.0 + time * 3.0) * 0.05;
      vec3 newPosition = position + normal * wave;

      gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
      }
      `;
      const fragmentShader = `
      uniform float time;
      uniform vec3 colorStart;
      uniform vec3 colorEnd;
      varying vec2 vUv;
      varying vec3 vNormal;

      void main() {
      // 渐变颜色
      vec3 color = mix(colorStart, colorEnd, vUv.y);

      // 添加发光效果
      float glow = abs(sin(vUv.y * 10.0 + time * 2.0)) * 0.3;
      color += glow * vec3(0.5, 0.8, 1.0);

      // 网格线效果
      float gridSize = 5.0;
      float gridWidth = 0.3;
      vec2 gridUv = fract(vUv * gridSize);

      // float verticalGrid = step(1.0 - gridWidth, gridUv.x); // 竖线
      float horizontalGrid = step(1.0 - gridWidth, gridUv.y); // 横线

      // 横向网格线透明
      if (horizontalGrid > 0.0) {
      discard; // 直接丢弃像素,完全透明
      }

      // 竖向网格线高亮
      // if (verticalGrid > 0.0) {
      // color = mix(color, vec3(1.0, 1.0, 1.0), 0.7);
      // }

      // gl_FragColor = vec4(color, color.r);
      // gl_FragColor = vec4(color, 0.6 + 0.4 * vUv.y); // 下方0.6,上方1.0
      gl_FragColor = vec4(color, 0.3 + 0.3 * vUv.y); // 下方0.3,上方0.6
      }
      `

      const material = new THREE.ShaderMaterial({
      uniforms: {
      time: { value: 0 },
      colorStart: { value: new THREE.Color(0x0984f7) },
      colorEnd: { value: new THREE.Color(0x60b0d6) }
      },
      vertexShader: vertexShader,
      fragmentShader: fragmentShader,
      transparent: true,
      side: THREE.DoubleSide,
      wireframe: false
      });
上一篇:
mapbox添加threejs原生实体
下一篇:
基于websocket数据使用threejs和tween实现数据平滑播放