记录一下常用的简单着色器效果
发表于:2025-03-31 | 分类: 前端
字数统计: 674 | 阅读时长: 3分钟 | 阅读量:
在进行 webgiswebgl 项目开发中,涉及到动态可视化效果时,着色器材质是一个常用的方案,除此之外就是使用一些第三方库在地图上层再添加一个 webgl 图层,但是这种方案太重,且不同的图层所在大面不在一面,所以叠加顺序遮盖可能不好处理。
在这里着重记录更新下常用的着色器效果
  • 首先是基本的用法
  1. 新建一个 geometry 容器
  2. 新建一个 shader 材质
    1. shader 材质包含 vertexShaderfragmentShader
    2. 顶点着色器( vertexShader )负责处理每个顶点的位置、变换等操作
    3. 片元着色器( fragmentShader )负责计算每个像素的颜色等最终渲染效果
  3. 根据容器和材质创建 mesh
  4. 添加 mesh 到场景中
  5. 根据需要调整 meshpositionrotation
  6. 调用 requestAnimationFrame 来更新着色器动态效果
  • 在这里只记录一下效果代码 即顶点着色器和片元着色器代码
    在实际项目使用中可以根据计算关系调整里面的数值进行效果微调
    1. 扩散波纹( shader 材质的 uniform 里需要定义 timecolor 供片元着色器读取 )
      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实现数据平滑播放