AlMustieles
AlMustieles

Reputation: 53

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...

Upvotes: 2

Views: 5157

Answers (1)

Halo
Halo

Reputation: 1970

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.

Upvotes: 5

Related Questions