three.jsshaderparticlesparticle-system

How to make particles in threejs take the shape of a model/object -onscroll


I am relatively new to ThreeJS. I want to make a website very similar to this one: Web de CraftedBYGC In which I make a system of particles that as the user scrolls they disperse and rejoin in a form. The truth is that I am very lost about where to start. I would greatly appreciate some help.

I tried to create a geometry with particle mesh and move the camera on scroll to simulate a little bit the effect, but the truth was very poor. I need to find another method and I don't know well what to do...


Solution

  • Below is a snippet of the working example:

    var webGLRenderer = initRenderer();
    var scene = new THREE.Scene();
    var camera = initCamera(new THREE.Vector3(-30, 40, 50));
    
    // call the render function
    var step = 0;
    
    var knot;
    
    // setup the control gui
    var controls = new function () {
      // we need the first child, since it's a multimaterial
      this.radius = 13;
      this.tube = 1.7;
      this.radialSegments = 156;
      this.tubularSegments = 12;
    
      this.redraw = function () {
        // remove the old plane
        if (knot) scene.remove(knot);
        // create a new one
        var geom = new THREE.TorusKnotGeometry(controls.radius, controls.tube, Math.round(controls.radialSegments), Math.round(controls.tubularSegments), Math.round(controls.p), Math.round(controls.q));
    
        knot = createPoints(geom);
    
        // add it to the scene.
        scene.add(knot);
      };
    
    };
    
    var gui = new dat.GUI();
    gui.add(controls, 'radius', 0, 40).onChange(controls.redraw);
    gui.add(controls, 'tube', 0, 40).onChange(controls.redraw);
    gui.add(controls, 'radialSegments', 0, 400).step(1).onChange(controls.redraw);
    gui.add(controls, 'tubularSegments', 1, 20).step(1).onChange(controls.redraw);
    
    controls.redraw();
    
    render();
    
    // from THREE.js examples
    function generateSprite() {
    
      var canvas = document.createElement('canvas');
      canvas.width = 16;
      canvas.height = 16;
    
      var context = canvas.getContext('2d');
      var gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
      gradient.addColorStop(0, 'rgba(255,255,255,1)');
      gradient.addColorStop(0.2, 'rgba(0,255,255,1)');
      gradient.addColorStop(0.4, 'rgba(0,0,64,1)');
      gradient.addColorStop(1, 'rgba(0,0,0,1)');
    
      context.fillStyle = gradient;
      context.fillRect(0, 0, canvas.width, canvas.height);
    
      var texture = new THREE.Texture(canvas);
      texture.needsUpdate = true;
      return texture;
    
    }
    
    function createPoints(geom) {
      var material = new THREE.PointsMaterial({
        color: 0xffffff,
        size: 3,
        transparent: true,
        blending: THREE.AdditiveBlending,
        map: generateSprite(),
        depthWrite: false // instead of sortParticles
      });
    
      var cloud = new THREE.Points(geom, material);
      return cloud;
    }
    
    
    function render() {
    
      knot.rotation.y = step += 0.01;
    
    
      // render using requestAnimationFrame
      requestAnimationFrame(render);
      webGLRenderer.render(scene, camera);
    }
    body {
      margin: 0;
      overflow: none
    }
    <!DOCTYPE html>
    
    <html>
    
    <head>
        <title>Example 07.11 - 3D Torusknot</title>
        <script type="text/javascript" charset="UTF-8" src="https://www.smartjava.org/ltjs3/libs/three/three.js"></script>
        <script src="https://www.smartjava.org/ltjs3/libs/three/controls/TrackballControls.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.9/dat.gui.min.js"></script>
        <script src="https://www.smartjava.org/ltjs3/src/js/util.js"></script>
    </head>
    
    <body>
        <div id="webgl-output">
    </body>
    
    </html>

    This is working on a TorusKnot, but you can apply the particles to a model, too. All you have to do is change the source.