webgl 给图片添加烟雾效果

466 阅读1分钟

实现效果

烟雾是动态的,因为gif录制不清楚,所有就截个图

代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>造型函数</title>
  </head>
  <body>
    <script src="https://unpkg.com/gl-renderer/dist/gl-renderer.js"></script>
    <canvas width="640" height="360"></canvas>
    <script>
     
      const vertex = `
      attribute vec2 a_vertexPosition;
      attribute vec2 uv;
      uniform vec2 translation;
      
      varying vec2 vUv;
      mat3 transformMatrix = mat3(
          1, 0, 0,
          0, 1, 0,
          translation, 1
        );

      void main() {
        gl_PointSize = 1.0;
        vUv = uv;
        vec3 pos = vec3(a_vertexPosition, 1);
        gl_Position = vec4(pos, 1);
      }
    `;

      const fragment = `
      #ifdef GL_ES
      precision highp float;
      #endif

      varying vec2 vUv;
      uniform sampler2D tMap;
      uniform sampler2D tPic;
      uniform float uTime;
      uniform vec2 resolution;

      float random(float x) {
        
        return fract(sin(x) * 10000.);
        
        }

      float noise(vec2 p) {
        
        return random(p.x + p.y * 10000.);
        
        }

        vec2 sw(vec2 p) { return vec2(floor(p.x), floor(p.y)); }
        vec2 se(vec2 p) { return vec2(ceil(p.x), floor(p.y)); }
        vec2 nw(vec2 p) { return vec2(floor(p.x), ceil(p.y)); }
        vec2 ne(vec2 p) { return vec2(ceil(p.x), ceil(p.y)); }

        float smoothNoise(vec2 p) {

        vec2 interp = smoothstep(0., 1., fract(p));
        float s = mix(noise(sw(p)), noise(se(p)), interp.x);
        float n = mix(noise(nw(p)), noise(ne(p)), interp.x);
        return mix(s, n, interp.y);
        
        }

        float fractalNoise(vec2 p) {

        float n = 0.;
        n += smoothNoise(p);
        n += smoothNoise(p * 2.) / 2.;
        n += smoothNoise(p * 4.) / 4.;
        n += smoothNoise(p * 8.) / 8.;
        n += smoothNoise(p * 16.) / 16.;
        n /= 1. + 1./2. + 1./4. + 1./8. + 1./16.;
        return n;
        
        }
        void main() {
          vec2 st = gl_FragCoord.xy / resolution;
          vec2 nuv = vec2(st.x - uTime / 6., st.y);
          st *= vec2(1., -1.);
        
        float x = fractalNoise(nuv * 1.5);
        vec3 final = mix(vec3(x), texture2D(tPic, vUv).xyz, pow(abs(st.y),.9));
        gl_FragColor = vec4(final, 1.);
      }
    `;

      (async function () {
        const canvas = document.querySelector("canvas");
        const renderer = new GlRenderer(canvas);
        const program = renderer.compileSync(fragment, vertex);
        renderer.useProgram(program);

      
        const picture = await renderer.loadTexture(
            "https://p1.ssl.qhimg.com/t01cca5849c98837396.jpg"
          )

        renderer.setMeshData([
          {
            positions: [
              [-1, -1],
              [-1, 1],
              [1, 1],
              [1, -1],
            ],
            attributes: {
              uv: [
                [0, 0],
                [0, 1],
                [1, 1],
                [1, 0],
              ],
            },
            cells: [
              [0, 1, 2],
              [2, 0, 3],
            ],
          },
        ]);
       
        
        function update(t) {
          renderer.uniforms.uTime = t / 1000;
          renderer.uniforms.resolution = [640, 360];
          renderer.uniforms.tPic = picture;
          
          renderer.render();

          requestAnimationFrame(update);
        }
        update(0);
      })();
    </script>
  </body>
</html>

tips

更多知识 参考 跟月影学可视化 还有 www.shadertoy.com/