• May 9, 2017Infinite Tubes with Three.js

    • /
    • /
    • in Best News, Freebies
    • /
    • by Juancho

    Since WebGL is getting more and more popular, we start to see a bunch of websites using it for amazing creative designs. The brand Fornasetti recently published their website using the power of WebGL for a very nice effect: an animation that let’s us seemingly travel through a tunnel with a changing pattern. The most interesting part of this experience is that the motion through the tunnel is controlled by the movement of the mouse. Today we’ll share some similar Three.js powered tunnel traveling experiments with you.

    Screenshot of Fornasetti's website
    Screenshot of Fornasetti‘s website.

    Getting Started

    For this demo we are using Three.js which is a useful library to create WebGL without getting your hands dirty. Before generating the tube we first need to setup a scene with a renderer, a camera and an empty scene.

    If you don’t feel comfortable using Three.js, I suggest you to first read a tutorial to get started with it. Rachel Smith wrote a good one in three parts over here.

    Once we have our scene ready we will proceed with these steps:

    1. Create a curve to determine the shape of the tube
    2. Generate the tube based on the curve
    3. Move everything forward
    4. Add some user interactions

    The curve

    Thanks to Three.js we have a useful function that allows us to create a curve based on a set of points. We first need to calculate the positions of those points. Once it’s done we can create our curve like this:

    // Create an empty array to stores the points
    var points = [];
    // Define points along Z axis
    for (var i = 0; i < 5; i += 1) {
        points.push(new THREE.Vector3(0, 0, 2.5 * (i / 4)));
    // Create a curve based on the points
    var curve = new THREE.CatmullRomCurve3(points)

    This curve will be updated later to modify the shape of the tube in real time. As you can see, all the points have the same X and Y positions. At the moment, the curve is a single straight line.

    The tube

    Now that we have a curve (that is not curved at all) we can create a tube using Three.js. To do so we need three parts: a geometry (the shape of the tube), a material (how it looks) and finally a mesh (the combination of the geometry and the material):

    // Create the geometry of the tube based on the curve
    // The other values are respectively : 
    // 70 : the number of segments along the tube
    // 0.02 : its radius (yeah it's a tiny tube)
    // 50 : the number of segments that make up the cross-section
    // false : a value to set if the tube is closed or not
    var tubeGeometry = new THREE.TubeGeometry(this.curve, 70, 0.02, 50, false);
    // Define a material for the tube with a jpg as texture instead of plain color
    var tubeMaterial = new THREE.MeshStandardMaterial({
        side: THREE.BackSide, // Since the camera will be inside the tube we need to reverse the faces
        map: rockPattern // rockPattern is a texture previously loaded
    // Repeat the pattern to prevent the texture being stretched
    tubeMaterial.map.wrapS = THREE.RepeatWrapping;
    tubeMaterial.map.wrapT = THREE.RepeatWrapping;
    tubeMaterial.map.repeat.set(30, 6);
    // Create a mesh based on tubeGeometry and tubeMaterial
    var tube = new THREE.Mesh(tubeGeometry, tubeMaterial);
    // Add the tube into the scene

    Move the tube forward

    This part is my favorite because to my surprise the animation did not work as I believed initially. I first thought that the tube was actually moving into the direction of the camera. Then, I suggested that the camera was moving inside the tube. But both ideas were wrong!

    The actual solution is really clever: nothing is “physically” moving forward in the scene beside the texture that is translated along the tube.

    To do so, we need to define an offset for the texture on every frame to create the illusion of motion.

    function updateMaterialOffset() {
      // Update the offset of the material with the defined speed
      tubeMaterial.map.offset.x += speed;

    User interactions

    The demo wouldn’t be that good if we didn’t implement some user interaction. When you move your mouse in the browser you can control the shape of the tube. The trick here is to update the points of the curve we created in the first step. Once the curve has been changed, we can update the tube accordingly with some transition.

    // Update the third point of the curve in X and Y axis
    curve.points[2].x = -mouse.position.x * 0.1;
    curve.points[2].y = mouse.position.y * 0.1;
    // Update the X position of the last point
    curve.points[4].x = -mouse.position.x * 0.1;

    That’s it?

    Well, sadly no, the code is a bit more complex than what I’ve explained in this article. But if you understood the steps above, you should have a global idea of how the demo works. If you want to understand even more, check the source code of the first demo; I’ve included a lot of comments. If you still have questions, do not hesitate to poke me on Twitter :)

    The demos

    Once you have a basic tube, you can improve it with many different options. Check out all the demos to give you some ideas!

    The demo with the brick pattern we’ve introduced above.
    Screenshot of a low poly particles demo - Infinite Tubes with Three.js
    Press your mouse down (or touch your screen) to release a rainbow of new particles!
    Screenshot of an hyperspace demo - Infinite Tubes with Three.js
    This demo is inspired by all the sci-fi movies with some time travel effect.
    Screenshot of a blood vessel demo
    Dive inside your body and explore a blood vessel :)
    Screenshot of a demo with a triangle tube - Infinite Tubes with Three.js
    Why should all tubes be round? This time we are traveling through a triangular one.
    InfiniteTubes_06 - Infinite Tubes with Three.js
    Try this demo on your phone or your tablet to control the tube with your device orientation!

    Thank you for reading this article!

    If you are excited by the demos in this article, please share your joy in the comments :)

    References and Credits

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

    Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 54 other subscribers