前端JS特效第18集:html5-实现canvas宇宙黑洞炫酷粒子动画特效

html5-实现canvas宇宙黑洞炫酷粒子动画特效,先来看看效果:

部分核心的代码如下(全部代码在文章末尾):

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>html5 canvas宇宙黑洞炫酷粒子动画特效</title>
<meta name="keywords" content="html5,canvas,宇宙黑洞,炫酷粒子,动画特效" />
<meta name="description" content="html5 canvas宇宙黑洞炫酷粒子动画特效代码下载。" /> 
<meta name="author" content="js代码(www.jsdaima.com)" />
<meta name="copyright" content="js代码(www.jsdaima.com)" />

<style>
body {
  margin: 0;
  padding: 0;
}

#container {
  position: fixed;
}</style>
</head>
<body>

<script src="js/three.min.js"></script>

<script id="vertexShader" type="x-shader/x-vertex">
    uniform float u_time;
  
    const float spawnrate = .01;
    const float life = 200.;
    const float fadetime = 20.;
    const int octaves = 5;
    const float seed = 43758.5453123;
    const float seed2 = 73156.8473192;
  
    float random(float val) {
      return fract(sin(val) * seed);
    }
  
    vec2 random2(vec2 st, float seed){
        st = vec2( dot(st,vec2(127.1,311.7)),
                  dot(st,vec2(269.5,183.3)) );
        return -1.0 + 2.0*fract(sin(st)*seed);
    }
  
    float random2d(vec2 uv) {
      return fract(
                sin(
                  dot( uv.xy, vec2(12.9898, 78.233) )
                ) * seed);
    }
  
  varying float v_z;
  
  float easeLinear(float time, float begin, float change, float duration)
  {
    return change * time / duration + begin;
  }
  vec2 easeLinear(float time, vec2 begin, vec2 change, float duration)
  {
    return change * time / duration + begin;
  }
      
  void main() {
    vec4 pos = vec4(position,1.0);
    float id = position.z;
    bool emitter = mod(id, 2.) == 0.;
    float rand = random(id);
    float rand1 = random(id + 1.);
    float pointsize = 100. * rand * rand1;
    
    // float spawnrate = spawnrate + (sin(u_time / 10.) + 1.) * .01;
    float time = mod(u_time - id * spawnrate, life);
    float step = time / life;
    bool alive = time >= 0.;
    
    vec2 polar = vec2(0., 0.);
    
    if(alive) {
      if(emitter) {
        // pos.xy = vec2(10. * rand);
        vec2 outerPolar = vec2(30. + sin(u_time / 50.) * 10., 200.);
        polar = easeLinear(time, vec2(sin(u_time / 50.), 100. + sin(u_time / 10.) * 50.), outerPolar, life);
        // polar.x += sin(u_time / 10. * rand) + 1.;
        polar.y += (sin((u_time + 100.) / 10. * rand) + 1.) * (polar.x * 2. + 10.);

        if(time < fadetime) {
          pointsize = easeLinear(time, 0., pointsize, fadetime);
        } else if(time > life - fadetime) {
          pointsize = easeLinear(time - life + fadetime, pointsize, -pointsize, fadetime);
        }
        pointsize *= (sin((u_time + 100.) / 10. * rand1) + 1.);
        pointsize *= cos(polar.x * 1.5 + u_time * .1) * .5 + 1.;
        pos.z = 100.;
      } else {
        // pos.xy = vec2(10. * rand);
        vec2 outerPolar = vec2(30. + sin(u_time / 50.) * 10. + 3.14, 200.);
        polar = easeLinear(time, vec2(sin(u_time / 50.) + 3.14, 100. + cos(u_time / 10.) * 50.), outerPolar, life);
        // polar.x += sin(u_time / 10. * rand) + 1.;
        polar.y += (sin((u_time + 100.) / 10. * rand) + 1.) * (polar.x * 2. + 10.);

        if(time < fadetime) {
          pointsize = easeLinear(time, 0., pointsize, fadetime);
        } else if(time > life - fadetime) {
          pointsize = easeLinear(time - life + fadetime, pointsize, -pointsize, fadetime);
        }
        pointsize *= 1. - (sin((u_time + 100.) / 10. * rand1) + 1.);
        // pointsize *= cos(polar.x * 1.5 + u_time * .1) * .5 + 1.;
        pos.z = 90.;
      }
    }
    
    pos.x += cos(polar.x) * polar.y;
    pos.y += sin(polar.x) * polar.y;
    
    v_z = pos.z / 100. + polar.x / 100.;
    gl_PointSize = pointsize;

    gl_Position = projectionMatrix *
                  modelViewMatrix *
                  pos;
  }
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
    uniform vec2 u_resolution;
    uniform float u_time;
    uniform sampler2D tSprite;
  
    varying float v_z;

    vec3 hsb2rgb( in vec3 c ){
      vec3 rgb = clamp(abs(mod(c.x*6.0+vec3(0.0,4.0,2.0),
                               6.0)-3.0)-1.0,
                       0.0,
                       1.0 );
      rgb = rgb*rgb*(3.0-2.0*rgb);
      return c.z * mix( vec3(1.0), rgb, c.y);
    }
  
    #define TAU 6.28318531
    float starSDF(vec2 st, int V, float s) {
      // st = st*4.-2.;
      float a = atan(st.y, st.x)/TAU;
      float seg = a * float(V);
      a = ((floor(seg) + 0.5)/float(V) + 
          mix(s,-s,step(.5,fract(seg)))) 
          * TAU;
      return abs(dot(vec2(cos(a),sin(a)),
                     st));
    }
  
    void main() {
      vec2 uv = (gl_FragCoord.xy - 0.5 * u_resolution.xy) / u_resolution.y;
      
      float dist;
      
      vec2 pointUV = gl_PointCoord.xy - .5 * v_z / v_z;
      dist = 1. - length(pointUV) * 3.;
      
      vec2 polar = vec2(atan(uv.y, uv.x), length(uv.xy));
      int points = int(dist * 5.);
      
      // gl_FragColor = vec4(hsb2rgb(vec3(polar.y / 3., 1. - v_z * sin(polar.y * u_time / 100.), polar.y * v_z / 10.)), dist);
      gl_FragColor = vec4(
        mix(
          vec3(5.0, 0., 0.), 
          vec3(.8, 1.5, .5), 
          clamp(dist * v_z, 0., 1.)
        ) * 
        dist, 
        smoothstep(0.6, .61 + v_z / 1.5, dist)
      );
      // gl_FragColor *= v_z / 2.;
      // gl_FragColor = vec4(vec3(.8, .8, .5), smoothstep(0.8, .81, dist));
      // gl_FragColor = vec4(v_z / 2.);
      // gl_FragColor = vec4(vec3(dist), dist);
    }
</script>


<div id="container"></div>

<script>
/*
Most of the stuff in here is just bootstrapping. Essentially it's just
setting ThreeJS up so that it renders a flat surface upon which to draw 
the shader. The only thing to see here really is the uniforms sent to 
the shader. Apart from that all of the magic happens in the HTML view
under the fragment shader.
*/

var container = void 0;
var camera = void 0,
    scene = void 0,
    renderer = void 0;
var uniforms = void 0;

function init() {
  container = document.getElementById('container');

  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 3000);
  camera.position.z = 600;
  // camera.position.x = -300;
  console.log(camera.lookAt(0, 0, 0));

  scene = new THREE.Scene();

  var geometry = new THREE.Geometry();

  var particleCount = 50000;
  // particleCount = 100;

  for (i = 0; i < particleCount; i++) {

    var vertex = new THREE.Vector3();

    vertex.x = 0;
    vertex.y = 0;
    vertex.z = i;

    geometry.vertices.push(vertex);
  }

  uniforms = {
    u_time: { type: "f", value: -10000.0 },
    u_resolution: { type: "v2", value: new THREE.Vector2() },
    u_mouse: { type: "v2", value: new THREE.Vector2() }
  };

  var material = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: document.getElementById('vertexShader').textContent,
    fragmentShader: document.getElementById('fragmentShader').textContent
  });
  material.transparent = true;
  material.blending = THREE.AdditiveBlending;
  material.depthTest = false;

  var mesh = new THREE.Points(geometry, material);
  // var mesh = new THREE.Mesh( geometry, starsMaterial );
  scene.add(mesh);

  renderer = new THREE.WebGLRenderer();
  // renderer.setPixelRatio( window.devicePixelRatio );
  renderer.setPixelRatio(1);

  container.appendChild(renderer.domElement);

  onWindowResize();
  window.addEventListener('resize', onWindowResize, false);

  document.onmousemove = function (e) {

    // camera.position.x = -300 + e.pageX / window.innerWidth * 600;
    // camera.position.y = 300 + e.pageY / window.innerHeight * -600;
    // console.log(camera.lookAt(0,0,0));

    uniforms.u_mouse.value.x = e.pageX;
    uniforms.u_mouse.value.y = e.pageY;
  };
}

function onWindowResize(event) {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  uniforms.u_resolution.value.x = renderer.domElement.width;
  uniforms.u_resolution.value.y = renderer.domElement.height;
}

function animate() {
  requestAnimationFrame(animate);
  render();
}

function render() {
  uniforms.u_time.value += 0.02;
  renderer.render(scene, camera);
}

init();
animate();</script>

</body>
</html>

全部代码:html5-实现canvas宇宙黑洞炫酷粒子动画特效

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值