Infinite Tubes with Three.js

Some WebGL experiments where the viewer seemingly travels through a textured tunnel. Powered by Three.js and inspired by the effect seen on fornasetti.com.

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.

Attention: You will need a recent browser that supports WebGL (> IE10) in order to see the demos.
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
scene.add(this.tubeMesh);

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;

Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.

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!

InfiniteTubes_01
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

Stay in the loop: Get your dose of frontend twice a week

Fresh news, inspo, code demos, and UI animations—zero fluff, all quality. Make your Mondays and Thursdays creative!

Feedback 18

Comments are closed.
    • Did you try the last demo ? You can control it with your gyroscope 🙂
      The VR demo would be awesome ! Maybe a future demo…

  1. Boy, you sure do like tunnels Louis! 😀 Love these and your CodePen posts too. Great work all around.

  2. Hey, I saw that you mentioned a VR mode would be awesome and I was really interested to see how trippy it was. I modified some of the code to duplicate the canvas across the screen. Works nicely on a mobile VR headset although look navigation is a bit buggy, check it out! https://umpox.github.io/tubeVR/index6.html

  3. Just awesome…Especially Particles & Bloodcells. Thank for sharing. What a visual stuff. Great job.

  4. Hello guys, I just found out. If you let the ” triangle ” tube for like 5 mins running it crashes.

    Anyone knows why?

  5. Woooooooooooow +200 respect. First thought which came up in my mind… Use the StarWars Wormhole Tube to navigate from page to page with VR Glasses glued onto your head would be just sooo freakin’ awesome xD!!